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()*
|
Iter:fold({self}, {init}, {f}) *Iter:fold()*
|
||||||
Fold an iterator or table into a single value.
|
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: ~
|
Parameters: ~
|
||||||
• {init} any Initial value of the accumulator.
|
• {init} any Initial value of the accumulator.
|
||||||
• {f} function(acc:any, ...):A Accumulation function.
|
• {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
|
The resulting table depends on the initial source in the iterator
|
||||||
pipeline. List-like tables and function iterators will be collected into a
|
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
|
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
|
the iterator pipeline, each value will be included in a table.
|
||||||
map-like table was used as the initial source, then a map-like table is
|
|
||||||
returned.
|
|
||||||
|
|
||||||
Examples: >lua
|
Examples: >lua
|
||||||
|
|
||||||
@ -3310,9 +3321,13 @@ Iter:totable({self}) *Iter:totable()*
|
|||||||
-- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
|
-- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
|
||||||
|
|
||||||
vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable()
|
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: ~
|
Return: ~
|
||||||
(table)
|
(table)
|
||||||
|
|
||||||
|
@ -18,14 +18,6 @@ ListIter.__call = function(self)
|
|||||||
return self:next()
|
return self:next()
|
||||||
end
|
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
|
---@private
|
||||||
local function unpack(t)
|
local function unpack(t)
|
||||||
if type(t) == 'table' and t.__n ~= nil then
|
if type(t) == 'table' and t.__n ~= nil then
|
||||||
@ -185,10 +177,10 @@ end
|
|||||||
|
|
||||||
--- Collect the iterator into a table.
|
--- Collect the iterator into a table.
|
||||||
---
|
---
|
||||||
--- The resulting table depends on the initial source in the iterator pipeline. List-like tables
|
--- The resulting table depends on the initial source in the iterator pipeline.
|
||||||
--- and function iterators will be collected into a list-like table. If multiple values are returned
|
--- List-like tables and function iterators will be collected into a list-like
|
||||||
--- from the final stage in the iterator pipeline, each value will be included in a table. If a
|
--- table. If multiple values are returned from the final stage in the iterator
|
||||||
--- map-like table was used as the initial source, then a map-like table is returned.
|
--- pipeline, each value will be included in a table.
|
||||||
---
|
---
|
||||||
--- Examples:
|
--- Examples:
|
||||||
--- <pre>lua
|
--- <pre>lua
|
||||||
@ -199,9 +191,13 @@ end
|
|||||||
--- -- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
|
--- -- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
|
||||||
---
|
---
|
||||||
--- vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable()
|
--- 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>
|
--- </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
|
---@return table
|
||||||
function Iter.totable(self)
|
function Iter.totable(self)
|
||||||
local t = {}
|
local t = {}
|
||||||
@ -239,17 +235,21 @@ function ListIter.totable(self)
|
|||||||
return Iter.totable(self)
|
return Iter.totable(self)
|
||||||
end
|
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.
|
--- 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
|
---@generic A
|
||||||
---
|
---
|
||||||
---@param init A Initial value of the accumulator.
|
---@param init A Initial value of the accumulator.
|
||||||
@ -783,7 +783,7 @@ function Iter.new(src, ...)
|
|||||||
count = count + 1
|
count = count + 1
|
||||||
local v = src[count]
|
local v = src[count]
|
||||||
if v == nil then
|
if v == nil then
|
||||||
return TableIter.new(src)
|
return Iter.new(pairs(src))
|
||||||
end
|
end
|
||||||
t[count] = v
|
t[count] = v
|
||||||
end
|
end
|
||||||
@ -827,25 +827,4 @@ function ListIter.new(t)
|
|||||||
return it
|
return it
|
||||||
end
|
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
|
return Iter
|
||||||
|
@ -3374,13 +3374,18 @@ describe('lua stdlib', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('handles map-like tables', function()
|
it('handles map-like tables', function()
|
||||||
local t = { a = 1, b = 2, c = 3 }
|
local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
|
||||||
local it = vim.iter(t):map(function(k, v)
|
|
||||||
if v % 2 ~= 0 then
|
if v % 2 ~= 0 then
|
||||||
return k:upper(), v * 2
|
return k:upper(), v * 2
|
||||||
end
|
end
|
||||||
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()
|
it('handles table values mid-pipeline', function()
|
||||||
local map = {
|
local map = {
|
||||||
|
Loading…
Reference in New Issue
Block a user