Expand the reduce function to both fold and reduce (#6337)

This commit is contained in:
Luther 2021-12-04 17:46:12 -05:00 committed by GitHub
parent e81cef3a08
commit bff219d41f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 8 deletions

View file

@ -14,4 +14,4 @@ global=false
unused=false
-- excluded files due to using lua 5.4 syntax that currently gets flagged as a syntax error
-- clear out once a newer Ubuntu LTS base is used for our docker images, which would then also have a newer luacheck available
exclude_files={"data/lua/core/wml.lua","data/lua/wml-flow.lua","data/lua/wml/find_path.lua","data/lua/wml/harm_unit.lua","data/lua/wml/modify_unit.lua","data/lua/wml/random_placement.lua"}
exclude_files={"data/lua/core/wml.lua","data/lua/wml-flow.lua","data/lua/wml/find_path.lua","data/lua/wml/harm_unit.lua","data/lua/wml/modify_unit.lua","data/lua/wml/random_placement.lua","data/lua/functional.lua"}

View file

@ -126,15 +126,28 @@ local known_operators = {
['or'] = function(a, b) return a or b end,
}
function functional.reduce(input, operator, identity)
if type(operator) == 'string' then
operator = known_operators[operator]
--- Reduce the elements of array t into a single value. operator is called as
--- 'operator(accumulator, element)' for every element in t. If a 3rd argument
--- is provided, which may be nil, it will be used as the accumulator when
--- calling operator on the first element. If there is no 3rd argument, the
--- first operator call will be on the first two elements. If there is no 3rd
--- argument and the array is empty, return nil. operator may be a function or a
--- binary Lua operator as a string.
function functional.reduce(t, operator, ...)
local f <const> = known_operators[operator] or operator
local function loop(init, i)
local value <const> = t[i]
if value == nil then
return init
end
return loop(f(init, value), i + 1)
end
local result = identity or 0
for _, v in ipairs(input) do
result = operator(result, v)
if select('#', ...) == 0 then
return loop(t[1], 2)
end
return result
return loop(select(1, ...), 1)
end
function functional.take_while(input, condition)

View file

@ -0,0 +1,29 @@
#textdomain wesnoth-test
# Tests for the functional.lua library
{GENERIC_UNIT_TEST "lua_functional" (
[event]
name = start
[lua]
code = <<
local fp <const> = wesnoth.require'lua/functional'
unit_test.assert_equal(
fp.reduce({}, function() end),
nil,
"reduce with empty array and no init doesn't return nil.")
unit_test.assert(
not fp.reduce({false, false}, 'or', false),
"reduce with false elements and 'or' operator returns a truthy value.")
unit_test.assert_equal(
fp.reduce({4, 5, 2}, '+', 0),
11,
"reduce does not calculate a sum correctly.")
unit_test.succeed()
>>
[/lua]
[/event]
)}

View file

@ -351,6 +351,7 @@
9 unknown_scenario_1_0
# Lua API tests
0 lua_functional
0 lua_map_find
0 mapgen_filter_range
0 mapgen_filter_terrain