mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
fix(iter): remove special case totable for map-like tables
This was originally meant as a convenience but prevents possible functionality. For example: -- Get the keys of the table with even values local t = { a = 1, b = 2, c = 3, d = 4 } vim.iter(t):map(function(k, v) if v % 2 == 0 then return k end end):totable() The example above would not work, because the map() function returns only a single value, and cannot be converted back into a table (there are many such examples like this). Instead, to convert an iterator into a map-like table, users can use fold(): vim.iter(t):fold({}, function(t, k, v) t[k] = v return t end)
This commit is contained in:
parent
6b96122453
commit
9489406879
@ -3037,6 +3037,19 @@ Iter:find({self}, {f}) *Iter:find()*
|
||||
Iter:fold({self}, {init}, {f}) *Iter:fold()*
|
||||
Fold an iterator or table into a single value.
|
||||
|
||||
Examples: >
|
||||
|
||||
-- Create a new table with only even values
|
||||
local t = { a = 1, b = 2, c = 3, d = 4 }
|
||||
local it = vim.iter(t)
|
||||
it:filter(function(k, v) return v % 2 == 0 end)
|
||||
it:fold({}, function(t, k, v)
|
||||
t[k] = v
|
||||
return t
|
||||
end)
|
||||
-- { b = 2, d = 4 }
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {init} any Initial value of the accumulator.
|
||||
• {f} function(acc:any, ...):A Accumulation function.
|
||||
@ -3297,9 +3310,7 @@ Iter:totable({self}) *Iter:totable()*
|
||||
The resulting table depends on the initial source in the iterator
|
||||
pipeline. List-like tables and function iterators will be collected into a
|
||||
list-like table. If multiple values are returned from the final stage in
|
||||
the iterator pipeline, each value will be included in a table. If a
|
||||
map-like table was used as the initial source, then a map-like table is
|
||||
returned.
|
||||
the iterator pipeline, each value will be included in a table.
|
||||
|
||||
Examples: >lua
|
||||
|
||||
@ -3310,9 +3321,13 @@ Iter:totable({self}) *Iter:totable()*
|
||||
-- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
|
||||
|
||||
vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable()
|
||||
-- { a = 1, c = 3 }
|
||||
-- { { 'a', 1 }, { 'c', 3 } }
|
||||
<
|
||||
|
||||
The generated table is a list-like table with consecutive, numeric
|
||||
indices. To create a map-like table with arbitrary keys, use
|
||||
|Iter:fold()|.
|
||||
|
||||
Return: ~
|
||||
(table)
|
||||
|
||||
|
@ -18,14 +18,6 @@ ListIter.__call = function(self)
|
||||
return self:next()
|
||||
end
|
||||
|
||||
--- Special case implementations for iterators on non-list tables.
|
||||
---@class TableIter : Iter
|
||||
local TableIter = {}
|
||||
TableIter.__index = setmetatable(TableIter, Iter)
|
||||
TableIter.__call = function(self)
|
||||
return self:next()
|
||||
end
|
||||
|
||||
---@private
|
||||
local function unpack(t)
|
||||
if type(t) == 'table' and t.__n ~= nil then
|
||||
@ -185,10 +177,10 @@ end
|
||||
|
||||
--- Collect the iterator into a table.
|
||||
---
|
||||
--- The resulting table depends on the initial source in the iterator pipeline. List-like tables
|
||||
--- and function iterators will be collected into a list-like table. If multiple values are returned
|
||||
--- from the final stage in the iterator pipeline, each value will be included in a table. If a
|
||||
--- map-like table was used as the initial source, then a map-like table is returned.
|
||||
--- The resulting table depends on the initial source in the iterator pipeline.
|
||||
--- List-like tables and function iterators will be collected into a list-like
|
||||
--- table. If multiple values are returned from the final stage in the iterator
|
||||
--- pipeline, each value will be included in a table.
|
||||
---
|
||||
--- Examples:
|
||||
--- <pre>lua
|
||||
@ -199,9 +191,13 @@ end
|
||||
--- -- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
|
||||
---
|
||||
--- vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable()
|
||||
--- -- { a = 1, c = 3 }
|
||||
--- -- { { 'a', 1 }, { 'c', 3 } }
|
||||
--- </pre>
|
||||
---
|
||||
--- The generated table is a list-like table with consecutive, numeric indices.
|
||||
--- To create a map-like table with arbitrary keys, use |Iter:fold()|.
|
||||
---
|
||||
---
|
||||
---@return table
|
||||
function Iter.totable(self)
|
||||
local t = {}
|
||||
@ -239,17 +235,21 @@ function ListIter.totable(self)
|
||||
return Iter.totable(self)
|
||||
end
|
||||
|
||||
---@private
|
||||
function TableIter.totable(self)
|
||||
local t = {}
|
||||
for k, v in self do
|
||||
t[k] = v
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
--- Fold an iterator or table into a single value.
|
||||
---
|
||||
--- Examples:
|
||||
--- <pre>
|
||||
--- -- Create a new table with only even values
|
||||
--- local t = { a = 1, b = 2, c = 3, d = 4 }
|
||||
--- local it = vim.iter(t)
|
||||
--- it:filter(function(k, v) return v % 2 == 0 end)
|
||||
--- it:fold({}, function(t, k, v)
|
||||
--- t[k] = v
|
||||
--- return t
|
||||
--- end)
|
||||
--- -- { b = 2, d = 4 }
|
||||
--- </pre>
|
||||
---
|
||||
---@generic A
|
||||
---
|
||||
---@param init A Initial value of the accumulator.
|
||||
@ -783,7 +783,7 @@ function Iter.new(src, ...)
|
||||
count = count + 1
|
||||
local v = src[count]
|
||||
if v == nil then
|
||||
return TableIter.new(src)
|
||||
return Iter.new(pairs(src))
|
||||
end
|
||||
t[count] = v
|
||||
end
|
||||
@ -827,25 +827,4 @@ function ListIter.new(t)
|
||||
return it
|
||||
end
|
||||
|
||||
--- Create a new TableIter
|
||||
---
|
||||
---@param t table Table to iterate over. For list-like tables, use ListIter.new instead.
|
||||
---@return Iter
|
||||
---@private
|
||||
function TableIter.new(t)
|
||||
local it = {}
|
||||
|
||||
local index = nil
|
||||
function it.next()
|
||||
local k, v = next(t, index)
|
||||
if k ~= nil then
|
||||
index = k
|
||||
return k, v
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(it, TableIter)
|
||||
return it
|
||||
end
|
||||
|
||||
return Iter
|
||||
|
@ -3374,13 +3374,18 @@ describe('lua stdlib', function()
|
||||
end)
|
||||
|
||||
it('handles map-like tables', function()
|
||||
local t = { a = 1, b = 2, c = 3 }
|
||||
local it = vim.iter(t):map(function(k, v)
|
||||
local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
|
||||
if v % 2 ~= 0 then
|
||||
return k:upper(), v * 2
|
||||
end
|
||||
end)
|
||||
eq({ A = 2, C = 6 }, it:totable())
|
||||
|
||||
local t = it:fold({}, function(t, k, v)
|
||||
t[k] = v
|
||||
return t
|
||||
end)
|
||||
eq({ A = 2, C = 6 }, t)
|
||||
end)
|
||||
|
||||
it('handles table values mid-pipeline', function()
|
||||
local map = {
|
||||
|
Loading…
Reference in New Issue
Block a user