Jump to content




Some lua tricks you may not have known...


106 replies to this topic

#61 Pharap

  • Members
  • 816 posts
  • LocationEngland

Posted 04 May 2013 - 03:37 PM

View PostKingdaro, on 04 May 2013 - 01:01 PM, said:

View PostPharap, on 04 May 2013 - 12:23 PM, said:

The len operator ( this thing # ) can be applied to tables to count all their numerical indexes, not just the arg table.
I thought that was pretty obvious, but alright.
Well, if you have to explicitly mention it for string it would be unfair to not explicitly mention its functioning on tables since it is actually classified as an operator.

View Posttheoriginalbit, on 04 May 2013 - 01:08 PM, said:

View PostKingdaro, on 04 May 2013 - 01:01 PM, said:

I thought that was pretty obvious, but alright.
I think the key thing stated there is "all their numerical indexes" ... so a table like so
local t = { 1, "hello", k = "world" }
would return 2 with both # and table.getn ...

It's table.maxn, but you're correct in the fact that they are pretty much the same functions, one is just easier to use.

#62 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 04 May 2013 - 10:33 PM

View PostPharap, on 04 May 2013 - 03:37 PM, said:

It's table.maxn
Actually its both... I aways forget about maxn so never say about it...

#63 Pharap

  • Members
  • 816 posts
  • LocationEngland

Posted 05 May 2013 - 06:53 AM

View Posttheoriginalbit, on 04 May 2013 - 10:33 PM, said:

View PostPharap, on 04 May 2013 - 03:37 PM, said:

It's table.maxn
Actually its both... I aways forget about maxn so never say about it...
Weird, seems kind of redundant.
I'm guessing getn is CC-specific since the official lua docs have it listed as maxn, no mention of getn.

#64 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 05 May 2013 - 06:58 AM

View PostPharap, on 05 May 2013 - 06:53 AM, said:

Weird, seems kind of redundant.
I'm guessing getn is CC-specific since the official lua docs have it listed as maxn, no mention of getn.
Yeh I guess so... talking about redundancies I think having
os.getComputerLabel()
and
os.computerLabel()
and the same with id.
both fairly redundant, but they are still there, so meh.

#65 Pharap

  • Members
  • 816 posts
  • LocationEngland

Posted 05 May 2013 - 09:27 AM

View Posttheoriginalbit, on 05 May 2013 - 06:58 AM, said:

View PostPharap, on 05 May 2013 - 06:53 AM, said:

Weird, seems kind of redundant.
I'm guessing getn is CC-specific since the official lua docs have it listed as maxn, no mention of getn.
Yeh I guess so... talking about redundancies I think having
os.getComputerLabel()
and
os.computerLabel()
and the same with id.
both fairly redundant, but they are still there, so meh.
Both of those are CC-specific functions, but yeah, there are a lot of redundancies lying around here and there.

#66 Majd Alfhaily

  • New Members
  • 2 posts
  • LocationEarth

Posted 20 May 2013 - 10:10 AM

Really nice information, knew some of them but most of them I didn't so it's really cool. Thanks!

#67 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 24 May 2013 - 08:38 PM

View PostPharap, on 04 May 2013 - 03:37 PM, said:

It's table.maxn, but you're correct in the fact that they are pretty much the same functions, one is just easier to use.
I actually just noticed in the Lua 5.2 docs that table.maxn is deprecated.

#68 Upgrade_Windows

  • Members
  • 27 posts
  • LocationUnited Kingdom

Posted 26 May 2013 - 12:30 PM

I know about most of these but for the ones I didn't know. wow. Thanks for the Lua tricks. :)

#69 Robotonic

  • Members
  • 19 posts
  • LocationEast Midlands, U.K.

Posted 26 May 2013 - 04:29 PM

These were actually very useful tips, thanks, this makes it a whole lot easier.

#70 JustPingo

  • Members
  • 108 posts
  • LocationFrance

Posted 26 May 2013 - 04:42 PM

I have already learnt all of this, but it's useful for people who don't know. Nice topic man.

I have already learnt all of this, but it's useful for people who don't know. Nice topic man.

#71 MaHuJa

  • Members
  • 26 posts

Posted 10 June 2013 - 10:08 AM

Quote

Also, when defining indices in tables, you can actually use semicolons instead of commas. For me, this is easier because I can rearrange elements of the table without having to redo my commas.
myTable = {
index1 = "foobar";
index2 = 1337;
}
Actually, t = { a, b, } is also valid, even without anything after the last comma. The explicit reason was to make it easier to make code that generates (lua coded) tables. Neither option applies to most languages.

Quote

var = condition and set_if_true or set_if_false
If the valid values for set_if_true include nil or false, it will not work as intended.


Quote

textutils.slowPrint('Your number is ' .. (num % 2 == 0 and 'even.' or 'odd.'))
It might surprise you to learn that this method is, while more compact in source code, worse performing than the previous version. (Performance being in server lag terms.)
The reason: string concatenations - or alterations in general - are expensive.

On that note, here's an important piece you've missed.
If you'd use
str = "H" .. "e" .. "l" .. "l" .. "o".. " ".. "W".. "o".. "r".. "l".. "d".. "!"
typically in the form of a loop that's accumulating output in a string, like this
text = ""
for i = 1,10 do 
  text = text .. ' ' .. i 
end
you should instead be doing
table.concat { 'H','e','l','l','o',' ','W','o','r','l','d', }
or
t = {}
for i = 1,10 do
  table.insert(t,i)
end
text = table.concat(t,' ') -- letting concat do the separator
if you don't want to kill the server.

If table.insert is verbose, t[#t+1]= should also be viable, I think.
(The above can also be done by metatable to make it transparent, fwiw.)

#72 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 10 June 2013 - 05:13 PM

View PostMaHuJa, on 10 June 2013 - 10:08 AM, said:

On that note, here's an important piece you've missed.
If you'd use
str = "H" .. "e" .. "l" .. "l" .. "o".. " ".. "W".. "o".. "r".. "l".. "d".. "!"
typically in the form of a loop that's accumulating output in a string, like this
text = ""
for i = 1,10 do
  text = text .. ' ' .. i
end
you should instead be doing
table.concat { 'H','e','l','l','o',' ','W','o','r','l','d', }
How exactly do you think table.concat works? you're comment above this one is saying about being more efficient and having good performance, yet here you insist on adding another function to the stack, incurring the overhead of the call, to just do the exact same thing as the loop... using table.concat does not add anything better than the loop...

View PostMaHuJa, on 10 June 2013 - 10:08 AM, said:

If table.insert is verbose, t[#t+1]= should also be viable, I think.
Also with this once, doing the following
local t = {}
for i = 1, 10 do
  t[#t + 1] = i
end
is far more efficient and has less overhead than
local t = {}
for i = 1, 10 do
  table.insert(t, i)
end


#73 Lyqyd

    Lua Liquidator

  • Moderators
  • 8,462 posts

Posted 10 June 2013 - 07:19 PM

table.concat is likely to be implemented java-side, though. There will certainly be some speed gains there.

#74 Kingdaro

    The Doctor

  • Members
  • 1,636 posts
  • Location'MURICA

Posted 11 June 2013 - 01:09 AM

View PostMaHuJa, on 10 June 2013 - 10:08 AM, said:

Quote

Also, when defining indices in tables, you can actually use semicolons instead of commas. For me, this is easier because I can rearrange elements of the table without having to redo my commas.
myTable = {
index1 = "foobar";
index2 = 1337;
}
Actually, t = { a, b, } is also valid, even without anything after the last comma. The explicit reason was to make it easier to make code that generates (lua coded) tables. Neither option applies to most languages.
Good point. I'll leave the bit in, though, because semicolons do look better (in my opinion) than unorderly trailing commas.

View PostMaHuJa, on 10 June 2013 - 10:08 AM, said:

Quote

var = condition and set_if_true or set_if_false
If the valid values for set_if_true include nil or false, it will not work as intended.
Also a good point. I might just redo that section altogether, because the "and" and "or" keywords expand to many more possibilities than just the ternary statement.

View PostMaHuJa, on 10 June 2013 - 10:08 AM, said:

Quote

textutils.slowPrint('Your number is ' .. (num % 2 == 0 and 'even.' or 'odd.'))
It might surprise you to learn that this method is, while more compact in source code, worse performing than the previous version. (Performance being in server lag terms.)
The reason: string concatenations - or alterations in general - are expensive.
The performance difference is not noticeable or relevant to this topic.

View PostMaHuJa, on 10 June 2013 - 10:08 AM, said:

On that note, here's an important piece you've missed.

If you'd use
str = "H" .. "e" .. "l" .. "l" .. "o".. " ".. "W".. "o".. "r".. "l".. "d".. "!"
typically in the form of a loop that's accumulating output in a string, like this
text = ""
for i = 1,10 do 
  text = text .. ' ' .. i 
end
you should instead be doing
table.concat { 'H','e','l','l','o',' ','W','o','r','l','d', }
or
t = {}
for i = 1,10 do
  table.insert(t,i)
end
text = table.concat(t,' ') -- letting concat do the separator
if you don't want to kill the server.

If table.insert is verbose, t[#t+1]= should also be viable, I think.
(The above can also be done by metatable to make it transparent, fwiw.)
Reiterating on my previously stated point, my focus in this topic is on the use and abuse of syntactic sugar, and not speed and performance. Even then, your example is only ten operations, and any significantly greater number is going to take a long time regardless of whichever method you're using.

Concatenation methods would not "kill the server".

#75 MaHuJa

  • Members
  • 26 posts

Posted 17 June 2013 - 07:13 PM

I hear you about the syntactic sugar - but the thread title was "lua tricks". And as "tricks" go, this one's big. Thus I believe bringing this up was appropriate. Of course, it's still up to you if you'll exclude it from the scope of the opening post, but at least I want to get the facts underlying that decision correct.

(FTR: I agree that the single concatenation as I first pointed out is irrelevant. Perhaps outside redpower computers, if one stripped down lua enough to run on it.)

The native lua implementation will allocate a new string each time you do a concatenation. Especially if you're concatenating lots of strings, or with the first ones being long, that means it'll be traversing over quite large amounts of memory, doing a full copy of all the accumulated content for each additional concatenation. This is explicitly not the case when using table.concat. Java has the same thing in the form of String vs StringBuilder, so I believe the LuaJ implementation merely "forwards" it, getting the same effect. (It would take a lot of effort to get it better, to handle a case which the language spec say's "don't do" about.)

Quote

any significantly greater number is going to take a long time regardless of whichever method you're using
The big clue is the difference between what numbers it takes to take a particular performance hit.

(Computer science incoming)
If we bump the number up to 1000 (1 character each string), then table.concat will be a total of 1000 chars allocated once, and written. (Excluding the "originals", that are created in any case.)
String concatenation becomes around 500000 allocated over several parts (so + allocation overhead) and written.
That's 499k more bytes moved around for the same end result, plus the 998 extra allocations (with their overhead) that needs to be done. It's damning even before cache misses become a topic.

Scale it up to 10000 and it's become a "significantly higher number" in your statement - but only for the string concatenation. So the correct version would be "any significantly greater number is going to take a long time depending on which method you're using"
Disclaimers/Known errors:
- Math done while tired. I think I got it at least approximate.
- Real operation would probably not be appending a single byte at a time, and possibly not all of them at once.
(though string concat would be worse off if there wasn't a corresponding reduction in operations count.)
- This doesn't account for the filling of the table which gets passed to table.concat, but that won't change it significantly.
- No accounting for separators in the string concatenation example.

(Did I miss anything? Please let me know.)


I have a habit of thinking in scale. Given a large server with enough users running multiple computers doing this, this difference has the potential to bring tick times up to unplayable levels ("killing the server") quickly. Assuming the CC memory limit guard picks up the unreferenced strings, or the JRE in use does emergency GC, it won't actually crash from an out of memory error any faster.


Quote

t[#t + 1] = i is far more efficient and has less overhead than table.insert(t, i)
You're probably right; the docs say table.insert position parameter defaults to #t+1.
Though I doubt the "far" part. Of course, if you have measured to find that, then I'll bow to that.
# will look up the metatable __len, and if it exists, call it. If there is no metatable or no __len, it may still be a function call or two itself. Coupled with whatever else you're doing in that loop, it's probably not going to be measurable, let alone significant. So in the end, that should be up to what the programmer finds the most readable. With a few lines of code already run, t:insert(i) or t:ins(i) are also options.

--

It is possible, btw, to make a "stringbuilder" type that will basically do the table.concat implicitly even if you're doing .. style concatenation. And otherwise transparently act like a string. You'd just have to invoke it explicitly when you begin. Lua is very flexible.

--

Thanks for making me think about what I've said.

#76 Tripy998

  • Members
  • 104 posts
  • LocationIn Front of Computer

Posted 21 June 2013 - 12:58 PM

This is so helpfull!

#77 Tripy998

  • Members
  • 104 posts
  • LocationIn Front of Computer

Posted 21 June 2013 - 12:59 PM

View PostPhyzgun, on 26 May 2013 - 04:29 PM, said:

These were actually very useful tips, thanks, this makes it a whole lot easier.
Off-Topic: I like your picture!
On-Topic: I agree

#78 FNCPro

  • Members
  • 64 posts

Posted 23 June 2013 - 02:07 PM

These lua tricks are very helpful!

#79 RoD

  • Members
  • 313 posts

Posted 25 June 2013 - 12:22 PM

Aweomse this is really usefull :D thanks

#80 Larandar

  • Members
  • 6 posts

Posted 27 June 2013 - 12:10 AM

Nice topic,
Thanks





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users