Yonaba / Moses

Utility library for functional programming in Lua

Home Page:http://yonaba.github.io/Moses

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Syntax and performance questions?

stuta opened this issue · comments

commented

Hello. This seems great, it is very good to have same syntax as underscore.

Hi @stuta

Moses have lots of functions which were inspired/taken from lodash. As such, they have a quite similar syntax. Either way, since Moses is Lua and lodash is JavaScript, there are indeed some differences. Check out the tutorial for examples.

Regarding LuaFun, no there are no performance tests comparing Moses to LuaFun that I know of. But I believe on some points, LuaFun might be faster than Moses, since it ws designed with performance in mind and taking advantage of LuaJIT.

commented

I tried this code:

local fn = require "fn" -- https://github.com/rtsisyk/luafun
local _ = require "moses" -- https://github.com/Yonaba/Moses/blob/master/doc/tutorial.md
local function filterFn(x)
	return x % 2 == 0
end
local function mapFn(x)
	return x + 0.1
end
local time1 = util.seconds()
local gen1 = fn.iter(arr):filter(filterFn):map(mapFn):take(3):totable()
time1 = util.seconds(time1)
print(string.format('%.6f seconds: %s', time1, table.concat(gen1, ', ')))
local time2 = util.seconds()
local gen2 = _(arr):filter(filterFn):map(mapFn):take(3):value()
time2 = util.seconds(time2)
print(string.format('%.6f seconds: %s', time2, table.concat(gen2, ', ')))
print(string.format("time1: %.6f / time2: %.6f, luafun is %.0f times faster than moses", time1, time2, time2/time1))

Result is different (filter is not working?), maybe I'm doing something wrong in moses?

0.000043 seconds: 2.1, 4.1, 6.1
0.943609 seconds: 1.1, 2.1, 3.1
time1: 0.000043 / time2: 0.943609, luafun is 21730 times faster than moses

I see why results are different. Actually, the syntax with Moses is defined with key-values pairs in mind as arguments for most functions. In your code, filter and map actually operate on keys of array arr, not its values. I believe your example should be refactored like this :

local function filterFn(i, x) return x % 2 == 0 end
local function mapFn(i, x) return x + 0.1 end
local gen2 = _(arr):filter(filterFn):map(mapFn):take(3):value()

Regarding the time difference, I am a bit surprised...Have you run both codes with LuaJIT ?

commented

I refactored the code.

Luajit 5.1:

0.000062 seconds: 2.1, 4.1, 6.1
3.179571 seconds: 2.1, 4.1, 6.1
time1: 0.000062 / time2: 3.179571, luafun is 51283 times faster than moses

Luajit 2.1 git:

0.000051 seconds: 2.1, 4.1, 6.1
0.958241 seconds: 2.1, 4.1, 6.1
time1: 0.000051 / time2: 0.958241, luafun is 18789 times faster than moses

There are some differences in times when running multiple times. Luafun does this lazily so the jit compiler does not kick in in 3 loops and luajit vs lua5.1 times are equal (depending on the run, times are very small).

Luafun is not maintained any more. If community could take all the good parts from there to moses it would be very good library.

commented

Fixed code:

local _ = require "moses" -- https://github.com/Yonaba/Moses/blob/master/doc/tutorial.md
local fn = require "luafun" -- https://github.com/rtsisyk/luafun
local function filterFn(x)
  return x % 2 == 0
end
local function mapFn(x)
  return x + 0.1
end
local function filterFn2(_, x)
  return x % 2 == 0
end
local function mapFn2(_, x)
  return x + 0.1
end
local time1 = os.clock()
local gen1 = fn.iter(arr):filter(filterFn):map(mapFn):take(3):totable()
time1 = os.clock() - time1
print(string.format('%.6f seconds: %s', time1, table.concat(gen1, ', ')))
local time2 = os.clock()
local gen2 = _(arr):filter(filterFn2):map(mapFn2):take(3):value()
time2 = os.clock() - time2
print(string.format('%.6f seconds: %s', time2, table.concat(gen2, ', ')))
print(string.format("time1: %.6f / time2: %.6f, luafun is %.0f times faster than moses", time1, time2, time2/time1))

Since a specific error was not reported here, I will close this issue.
Thanks.