table comprehensions support single expression that returns a pair

This commit is contained in:
leaf corcoran 2012-10-03 11:30:23 -07:00
parent 867989b4f7
commit 14db695560
6 changed files with 129 additions and 17 deletions

View File

@ -436,6 +436,18 @@ for a few numbers.
sqrts = {i, math.sqrt i for i in *numbers} sqrts = {i, math.sqrt i for i in *numbers}
``` ```
The key-value tuple in a table comprehension can also come from a single
expression, in which case the expression should return two values. The
first is used as the key and the second is used as the value:
In this example we convert an array of pairs to a table where the first item in
the pair is the key and the second is the value.
```moon
tuples = {{"hello", "world"}, {"foo", "bar"}}
tbl = {unpack tuple for tuple in *tuples}
```
### Slicing ### Slicing
A special syntax is provided to restrict the items that are iterated over when A special syntax is provided to restrict the items that are iterated over when
@ -480,7 +492,7 @@ There are two for loop forms, just like in Lua. A numeric one and a generic one:
print key, value print key, value
``` ```
The slicing and `*` operators can be used, just like with table comprehensions: The slicing and `*` operators can be used, just like with comprehensions:
```moon ```moon
for item in *items[2,4] for item in *items[2,4]

View File

@ -413,7 +413,7 @@ local build_grammar = wrap_env(function()
Comprehension = sym"[" * Exp * CompInner * sym"]" / mark"comprehension", Comprehension = sym"[" * Exp * CompInner * sym"]" / mark"comprehension",
TblComprehension = sym"{" * Exp * (sym"," * Exp)^-1 * CompInner * sym"}" / mark"tblcomprehension", TblComprehension = sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension",
CompInner = Ct(CompFor * CompClause^0), CompInner = Ct(CompFor * CompClause^0),
CompFor = key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"for", CompFor = key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"for",

View File

@ -1231,8 +1231,11 @@ Value = Transformer({
return a:wrap(node) return a:wrap(node)
end, end,
tblcomprehension = function(self, node) tblcomprehension = function(self, node)
local _, key_exp, value_exp, clauses = unpack(node) local _, explist, clauses = unpack(node)
local key_exp, value_exp = unpack(explist)
local accum = NameProxy("tbl") local accum = NameProxy("tbl")
local inner
if value_exp then
local dest = build.chain({ local dest = build.chain({
base = accum, base = accum,
{ {
@ -1240,12 +1243,34 @@ Value = Transformer({
key_exp key_exp
} }
}) })
local inner = build.assign_one(dest, value_exp) inner = {
build.assign_one(dest, value_exp)
}
else
local key_name, val_name = NameProxy("key"), NameProxy("val")
local dest = build.chain({
base = accum,
{
"index",
key_name
}
})
inner = {
build.assign({
names = {
key_name,
val_name
},
values = {
key_exp
}
}),
build.assign_one(dest, val_name)
}
end
return build.block_exp({ return build.block_exp({
build.assign_one(accum, build.table()), build.assign_one(accum, build.table()),
construct_comprehension({ construct_comprehension(inner, clauses),
inner
}, clauses),
accum accum
}) })
end, end,

View File

@ -654,15 +654,27 @@ Value = Transformer {
a\wrap node a\wrap node
tblcomprehension: (node) => tblcomprehension: (node) =>
_, key_exp, value_exp, clauses = unpack node _, explist, clauses = unpack node
key_exp, value_exp = unpack explist
accum = NameProxy "tbl" accum = NameProxy "tbl"
inner = if value_exp
dest = build.chain { base: accum, {"index", key_exp} } dest = build.chain { base: accum, {"index", key_exp} }
inner = build.assign_one dest, value_exp { build.assign_one dest, value_exp }
else
-- If we only have single expression then
-- unpack the result into key and value
key_name, val_name = NameProxy"key", NameProxy"val"
dest = build.chain { base: accum, {"index", key_name} }
{
build.assign names: {key_name, val_name}, values: {key_exp}
build.assign_one dest, val_name
}
build.block_exp { build.block_exp {
build.assign_one accum, build.table! build.assign_one accum, build.table!
construct_comprehension {inner}, clauses construct_comprehension inner, clauses
accum accum
} }

View File

@ -1,4 +1,6 @@
-- see lists.moon for list comprehension tests
items = {1,2,3,4,5,6} items = {1,2,3,4,5,6}
out = {k,k*2 for k in items} out = {k,k*2 for k in items}
@ -7,3 +9,11 @@ x = hello: "world", okay: 2323
copy = {k,v for k,v in pairs x when k != "okay"} copy = {k,v for k,v in pairs x when k != "okay"}
--
{ unpack(x) for x in yes }
{ unpack(x) for x in *yes }
{ xxxx for x in yes }
{ unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} }

View File

@ -26,3 +26,56 @@ local copy = (function()
end end
return _tbl_0 return _tbl_0
end)() end)()
local _ = (function()
local _tbl_0 = { }
for x in yes do
local _key_0, _val_0 = unpack(x)
_tbl_0[_key_0] = _val_0
end
return _tbl_0
end)()
_ = (function()
local _tbl_0 = { }
local _list_0 = yes
for _index_0 = 1, #_list_0 do
x = _list_0[_index_0]
local _key_0, _val_0 = unpack(x)
_tbl_0[_key_0] = _val_0
end
return _tbl_0
end)()
_ = (function()
local _tbl_0 = { }
for x in yes do
local _key_0, _val_0 = xxxx
_tbl_0[_key_0] = _val_0
end
return _tbl_0
end)()
_ = (function()
local _tbl_0 = { }
local _list_0 = {
{
1,
2
},
{
3,
4
}
}
for _index_0 = 1, #_list_0 do
x = _list_0[_index_0]
local _key_0, _val_0 = unpack((function()
local _accum_0 = { }
local _len_0 = 0
for i, a in ipairs(x) do
_len_0 = _len_0 + 1
_accum_0[_len_0] = a * i
end
return _accum_0
end)())
_tbl_0[_key_0] = _val_0
end
return _tbl_0
end)()