If args is valid, assert it's a table.
Provides a clear and immediate error message when you convert
add_timeout() to call().
Also add type_or_nil. Very useful for optional parameters like this one.
Seems clearer than checking the arg first:
if args then assert:type() end
See Davidobot/love.js#54.
lovejs crashes love with "attempt to yield across metamethod/C-call
boundary" when you try to yield in a coroutine, so we skip wrapping.
We lose the coroutine-local callstack, but at least it works.
Here's my repro:
local color = {
purple = {0.25, 0.09, 0.28, 1},
white = {0.89, 0.91, 0.90, 1},
}
local ball = {
x = 100,
y = 100,
r = 20,
}
local S = {}
local input = {
vanilla = 'v',
async = 'c',
quit = 'escape',
}
function love.load()
S.coro = async()
end
local function coro_fn()
S.async_running = true
for i=1,100 do
color.purple[4] = i / 100
coroutine.yield()
end
color.purple[4] = 1
S.async_running = false
return true
end
function love.update(dt)
S.coro:update(dt)
if S.vanilla then
local success, result = coroutine.resume(S.vanilla)
if result then
print("coroutine cleared")
S.vanilla = nil
end
end
if not S.async_running then
if love.keyboard.isDown(input.vanilla) then
S.vanilla = coroutine.create(coro_fn)
print("raw coroutine started")
elseif love.keyboard.isDown(input.async) then
print("Starting async call coroutine from update")
S.coro:call(coro_fn)
elseif love.keyboard.isDown(input.quit) then
love.event.quit()
end
end
end
function love.draw()
love.graphics.setColor(color.purple)
love.graphics.circle("fill", ball.x, ball.y, ball.r)
love.graphics.setColor(color.white)
local str = "To start a coroutine:"
for key,val in pairs(input) do
str = ("%s\n%s: %s"):format(str, key, val)
end
love.graphics.printf(str, 5,5, 200, "left")
end
Allowing shallow_copy/deep_copy to accept any type makes it easier to
write generic code where you just want to copy some input without
knowing anything about it. Like an event system, save system, etc.
Add corresponding test.
Tests pass
No bugs here, but giving an initial value can hide cases where we fail
to set a value. Use an assert instead so we can see errors if we change
and break this code.
Except break_next which goes out of scope after it's assigned (I guess
it used to be outside the loop).
Fix bug where circle_aabb_overlap wouldn't have the same results as
aabb_circle_overlap.
b_hs was unused, but the function we call expects a_hs as the first
argument. Looks like this circle_aabb_overlap is just flipping
the arguments to aabb_circle_overlap (and for circle_aabb_collide), so
it should match arguments.
Not sure what hs means. Box size?
Fix crash when using append_inplace without batteries:export().
If you don't export batteries into the global namespace to stomp table,
then append_inplace would access a nil function because it's using table
instead of tablex.
We still use table inside init, but that's after we export to global
namespace.
Fix shadowing by using variables with a different name or _.
I don't think any of these warnings were actual bugs and fixed them to
maintain the same behaviour.
Run luacheck on CI to catch subtle errors.
Add a luacheckrc that ensures current code issues no warnings. We should
eventually try to remove many of these ignores.
As a new user, there were things I was skeptical about and after digging
in, these were my conclusions.
Compared to the simple and obvious lua wiki solutions, batteries' string
functions are slightly faster. GC is the same.
Test
local str = "hello world"
local fn = function()
local x = 0
if stringx.ends_with(str, "h") then
x = x + 1
end
if stringx.ends_with(str, "helll") then
x = x + 1
end
if stringx.ends_with(str, "helicopter") then
x = x + 1
end
end
local pretty = require "inspect"
print("stringx =", pretty({
time_taken = {measure.time_taken(fn, 10000)},
memory_taken = {measure.memory_taken(fn, 10000)}
}))
local function starts_with(str, prefix)
return str:find(prefix, 1, true) == 1
end
local function ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
local fn = function()
local x = 0
if ends_with(str, "h") then
x = x + 1
end
if ends_with(str, "helll") then
x = x + 1
end
if ends_with(str, "helicopter") then
x = x + 1
end
end
print("find =", pretty({
time_taken = {measure.time_taken(fn, 10000)},
memory_taken = {measure.memory_taken(fn, 10000)}
}))
starts_with
===========
stringx = {
memory_taken = { 0, 0, 0 },
time_taken = { 1.5098012518138e-007, 9.988434612751e-008, 2.1699932403862e-005 }
}
find = {
memory_taken = { 0, 0, 0 },
time_taken = { 2.7349997544661e-007, 1.9988510757685e-007, 9.1999536380172e-006 }
}
ends_with
=========
stringx = {
memory_taken = { 0, 0, 0 },
time_taken = { 9.0479978825897e-008, 0, 2.5199959054589e-005 }
}
find = {
memory_taken = { 0, 0, 0 },
time_taken = { 2.1833006758243e-007, 1.9988510757685e-007, 6.1000464484096e-006 }
}
Replace copy with shallow_copy, deep_copy.
Replace overlay with shallow_overlay, deep_overlay.
Significant rewrite of these functions and their semantics to update to
the note above them.
Add corresponding tests.
The second loop doesn't care if the values are equal. It only checks if
the keys are there. The first loop already checked for equality.
Add tests to prove correctness using testy.lua.