Type inferencing of filter style functions
Opened this issue · 4 comments
lewis6991 commented
Given:
---@generic T
---@param f fun(a: T)
---@param t table<any, T>
---@return T[] (table)
local function tbl_filter(f, t)
return t
end
---@type string[]
local s = {'a', 'b', 'c'}
local r1 = tbl_filter(function(a) end, s)
r1
is inferred as unknown[]
because a
is unknown
despite s
being known. However, could we infer a
from s
and force the typechecker to insist a
is a string?
If I remove the type from a
:
---@generic T
---@param f fun(a)
---@param t table<any, T>
---@return T[] (table)
local function tbl_filter2(f, t)
return t
end
local r2 = tbl_filter2(function(_) end, s)
r2
is now inferred as string[]
because only s
is used to infer the type.
sumneko commented
I don't know how to design a strict rule.
lewis6991 commented
- Look at all the sources of T
- Make sure all the known sources match
- For any unknown sources which come anonymous function arguments (or return values) insist it is the same type from the known sources.
Would that work?
sumneko commented
I will try it, thank you.
itsfrank commented
Interestingly, this does work as expected when using list T[]
instead of table<any,T>
(using version 3.7.3
)
code:
---Filter a list
---@generic T
---@param list T[]
---@param p fun(v:T):boolean
---@return T[]
function iter.filter(list, p)
local filtered = {}
for _, v in ipairs(list) do
if p(v) then
table.insert(filtered, v)
end
end
return filtered
end
-- number[]
local input = { 1, 2, 3, 4, 5 }
local filtered = iter.filter(input, function(v)
return v % 2 == 0
end)