Page 1 of 5

Share your favourite helper functions

Posted: Tue Nov 13, 2012 5:07 am
by benhumphreys
I've found that building up a library of helper functions can really speed up programming and debugging in Löve/Lua.
I've called them "helper functions" in the title, but basically any techniques, modules, functions etc. that you use a lot and have saved you a lot of time would be great. Share them! :D

I'll start:

Coloured Logging Function
Prints out the filename and line where the log command was called. This coupled with Kikito's ansicolors has made debugging a lot easier for me. You can find where that print statement is hiding in a large project, and visually trace through the code.
You can make a key toggle helper.DEBUG_ON to see how your game performs without all the STDOUT spam slowing it down.

It looks like:
helper-log.png
helper-log.png (51.27 KiB) Viewed 4570 times

Code: Select all

local colors = require("ansicolors")
helper.DEBUG_ON = true
function log(...)
  if not helper.DEBUG_ON then return end
  local info = debug.getinfo(2, "Sl")
  if info then
    print(string.format(colors("%{cyan}[%s]:%{green}%d%{reset}"), info.short_src, info.currentline), ...)
  else
    print(...)
  end
end

-- Call it with:
log("Some result is ", result)

Re: Share your favourite helper functions

Posted: Tue Nov 13, 2012 10:54 pm
by Inny
Here's a neat one:

Code: Select all

function randomPick(...)
  return select(math.random(1, select('#', ...)), ...)
end

print( randomPick("apple", "banana", "orange", "karl rove") )
If we get a lot of stuff, it'd be cool to see it added to https://love2d.org/wiki/Category:Snippets or even to http://lua-users.org/wiki/

Also, check those two places for other useful bits of lua code.

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 8:57 am
by ivan
This one is a classic:

Code: Select all

table.find = function(self, e)
  for i, v in pairs(self) do
    if v == e then
      return i
    end
  end
end

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 9:34 am
by Azhukar
ivan wrote:This one is a classic:

Code: Select all

table.find = function(self, e)
  for i, v in pairs(self) do
    if v == e then
      return i
    end
  end
end
You needlessly recreate the function for every table created this way. It would be more efficient to declare said function outside of the table and assign it to every table you want, assuming you're using more than 1 table with that function.

EDIT: This post is made out of finely minced brain fart. :crazy:

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 9:42 am
by Robin
Azhukar wrote:You needlessly recreate the function for every table created this way. It would be more efficient to declare said function outside of the table and assign it to every table you want, assuming you're using more than 1 table with that function.
That's nonsense.

You use it like

Code: Select all

numbers = {1, 10, 100, 1000}
print(table.find(numbers, 100)) -- prints 3

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 9:44 am
by slime
Azhukar wrote:
ivan wrote:This one is a classic:

Code: Select all

table.find = function(self, e)
  for i, v in pairs(self) do
    if v == e then
      return i
    end
  end
end
You needlessly recreate the function for every table created this way. It would be more efficient to declare said function outside of the table and assign it to every table you want, assuming you're using more than 1 table with that function.
the "table" global table is a library of functions. It doesn't get copied for every new table created.

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 10:20 am
by Azhukar
slime wrote:the "table" global table is a library of functions. It doesn't get copied for every new table created.
Derp, thought he used "table" as a placeholder for his table name. :(

Anyway to make up for this derail, here's a copytable function I use often:

Code: Select all

local function copytable(t,k)
	k = k or {}
	local r = {}
	k[t] = r
	for i,v in pairs(t) do
		if (type(v)=="table") then
			if (k[v]) then
				r[i] = k[v]
			else
				r[i] = copytable(v,k)
			end
		else
			r[i] = v
		end
	end
	return r
end

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 10:31 am
by Roland_Yonaba
Hi community,

Maybe some of you might want to take a closer look at Moses.lua and its samples. :awesome:

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 1:11 pm
by spir
benhumphreys wrote:I've found that building up a library of helper functions can really speed up programming and debugging in Löve/Lua.
I've called them "helper functions" in the title, but basically any techniques, modules, functions etc. that you use a lot and have saved you a lot of time would be great. Share them! :D
This is a great idea, however:

* It should be split into at least 3 threads:
1. Lua general purpose helpers.
2. Game-programming oriented lua helpers.
3. Löve-specific helpers.
I guess we should concentrate on 3., maybe 2., but there are probably resources on 2. on various web sites, no? For 1., the Lua users' wiki is full of tips, examples, and "helpers" -- and other resources like libs.

* This can quickly inflate! to the point beeing unusable [*]. Maybe we could just quickly introduce helpers here (or in more specific threads) and from that build wiki pages with the material?

However, here are my first 2 contributions:

Code: Select all

note = print
I always use "note" for debug output, that way I don't have to hunt for debug output lines in code when everything (endly) works fine (seems to).

And here's my printf:

Code: Select all

-- types that have a custom format (%d %f %s) (nil and boolean auto-convert)
local format_types = {["nil"]=true, boolean=true, number=true, string=true}

notef  = function (fmt, ...)
   --~ local items = table.pack(...)
   local items = {...}
   local item
   for i = 1, #items do
      item = items[i]
      if not format_types[type(item)] then items[i] = tostring(item) end
   end
   print( format(fmt, unpack(items)) ) 
end
Usage:

Code: Select all

notef("%d | %8.3f | %s | %s | %s | %s",
   1, -1.12345, "one", {1,2,3}, A{1,2,3}, function()end)
--> 1 |   -1.123 | one | table: 0x9455e38 | A{1, 2, 3} | function: 0x949be48
''Note'': When LÖVE switches to Lua 5.2, we can get rid of tostring conversions, %s now auto-stringifies non-string arguments. Also, there is a highly useful "table.pack" func symetric to unpack (and which correctly handles nil's, unlike just surrouding with braces as in {...}).

Denis

[*] On my side, every "module" starts with "require stdlib" where stdlib is my personal Lua lib of helpers, which i'm just starting to recreate for the occasion of playing with Löve, and is already after a few days about 1000 LoC.

EDIT1: I also have write and writef too funcs which just do not add a newline; very handy to follow the behaviour of a sequence of code...

EDIT2: But my dream tool func is rather:

Code: Select all

   local x = 1
   note(x)      --> "x : 1"
   --> not just "1"
Option: add in parens the func name and line number of the "note" statement:

Code: Select all

f = function (x)
   local x = 1
   note(x)      --> "x : 1 (f, 333)"
end

Re: Share your favourite helper functions

Posted: Wed Nov 14, 2012 2:54 pm
by Robin
spir wrote:EDIT2: But my dream tool func is rather:

Code: Select all

   local x = 1
   note(x)      --> "x : 1"
   --> not just "1"
Option: add in parens the func name and line number of the "note" statement:

Code: Select all

f = function (x)
   local x = 1
   note(x)      --> "x : 1 (f, 333)"
end
Those two aren't really possible in Lua (unless you hack together a preprocessor or manage to incorporate MetaLua or something).