Skip to content

Commit 14db695

Browse files
committed
table comprehensions support single expression that returns a pair
1 parent 867989b commit 14db695

File tree

6 files changed

+129
-17
lines changed

6 files changed

+129
-17
lines changed

docs/reference.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,18 @@ for a few numbers.
436436
sqrts = {i, math.sqrt i for i in *numbers}
437437
```
438438

439+
The key-value tuple in a table comprehension can also come from a single
440+
expression, in which case the expression should return two values. The
441+
first is used as the key and the second is used as the value:
442+
443+
In this example we convert an array of pairs to a table where the first item in
444+
the pair is the key and the second is the value.
445+
446+
```moon
447+
tuples = {{"hello", "world"}, {"foo", "bar"}}
448+
tbl = {unpack tuple for tuple in *tuples}
449+
```
450+
439451
### Slicing
440452

441453
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:
480492
print key, value
481493
```
482494

483-
The slicing and `*` operators can be used, just like with table comprehensions:
495+
The slicing and `*` operators can be used, just like with comprehensions:
484496

485497
```moon
486498
for item in *items[2,4]

moonscript/parse.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ local build_grammar = wrap_env(function()
413413

414414
Comprehension = sym"[" * Exp * CompInner * sym"]" / mark"comprehension",
415415

416-
TblComprehension = sym"{" * Exp * (sym"," * Exp)^-1 * CompInner * sym"}" / mark"tblcomprehension",
416+
TblComprehension = sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension",
417417

418418
CompInner = Ct(CompFor * CompClause^0),
419419
CompFor = key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"for",

moonscript/transform.lua

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,21 +1231,46 @@ Value = Transformer({
12311231
return a:wrap(node)
12321232
end,
12331233
tblcomprehension = function(self, node)
1234-
local _, key_exp, value_exp, clauses = unpack(node)
1234+
local _, explist, clauses = unpack(node)
1235+
local key_exp, value_exp = unpack(explist)
12351236
local accum = NameProxy("tbl")
1236-
local dest = build.chain({
1237-
base = accum,
1238-
{
1239-
"index",
1240-
key_exp
1237+
local inner
1238+
if value_exp then
1239+
local dest = build.chain({
1240+
base = accum,
1241+
{
1242+
"index",
1243+
key_exp
1244+
}
1245+
})
1246+
inner = {
1247+
build.assign_one(dest, value_exp)
12411248
}
1242-
})
1243-
local inner = build.assign_one(dest, value_exp)
1249+
else
1250+
local key_name, val_name = NameProxy("key"), NameProxy("val")
1251+
local dest = build.chain({
1252+
base = accum,
1253+
{
1254+
"index",
1255+
key_name
1256+
}
1257+
})
1258+
inner = {
1259+
build.assign({
1260+
names = {
1261+
key_name,
1262+
val_name
1263+
},
1264+
values = {
1265+
key_exp
1266+
}
1267+
}),
1268+
build.assign_one(dest, val_name)
1269+
}
1270+
end
12441271
return build.block_exp({
12451272
build.assign_one(accum, build.table()),
1246-
construct_comprehension({
1247-
inner
1248-
}, clauses),
1273+
construct_comprehension(inner, clauses),
12491274
accum
12501275
})
12511276
end,

moonscript/transform.moon

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -654,15 +654,27 @@ Value = Transformer {
654654
a\wrap node
655655

656656
tblcomprehension: (node) =>
657-
_, key_exp, value_exp, clauses = unpack node
657+
_, explist, clauses = unpack node
658+
key_exp, value_exp = unpack explist
658659

659660
accum = NameProxy "tbl"
660-
dest = build.chain { base: accum, {"index", key_exp} }
661-
inner = build.assign_one dest, value_exp
661+
662+
inner = if value_exp
663+
dest = build.chain { base: accum, {"index", key_exp} }
664+
{ build.assign_one dest, value_exp }
665+
else
666+
-- If we only have single expression then
667+
-- unpack the result into key and value
668+
key_name, val_name = NameProxy"key", NameProxy"val"
669+
dest = build.chain { base: accum, {"index", key_name} }
670+
{
671+
build.assign names: {key_name, val_name}, values: {key_exp}
672+
build.assign_one dest, val_name
673+
}
662674

663675
build.block_exp {
664676
build.assign_one accum, build.table!
665-
construct_comprehension {inner}, clauses
677+
construct_comprehension inner, clauses
666678
accum
667679
}
668680

tests/inputs/comprehension.moon

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11

2+
-- see lists.moon for list comprehension tests
3+
24
items = {1,2,3,4,5,6}
35
out = {k,k*2 for k in items}
46

@@ -7,3 +9,11 @@ x = hello: "world", okay: 2323
79

810
copy = {k,v for k,v in pairs x when k != "okay"}
911

12+
--
13+
14+
{ unpack(x) for x in yes }
15+
{ unpack(x) for x in *yes }
16+
17+
{ xxxx for x in yes }
18+
{ unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} }
19+

tests/outputs/comprehension.lua

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,57 @@ local copy = (function()
2525
end
2626
end
2727
return _tbl_0
28+
end)()
29+
local _ = (function()
30+
local _tbl_0 = { }
31+
for x in yes do
32+
local _key_0, _val_0 = unpack(x)
33+
_tbl_0[_key_0] = _val_0
34+
end
35+
return _tbl_0
36+
end)()
37+
_ = (function()
38+
local _tbl_0 = { }
39+
local _list_0 = yes
40+
for _index_0 = 1, #_list_0 do
41+
x = _list_0[_index_0]
42+
local _key_0, _val_0 = unpack(x)
43+
_tbl_0[_key_0] = _val_0
44+
end
45+
return _tbl_0
46+
end)()
47+
_ = (function()
48+
local _tbl_0 = { }
49+
for x in yes do
50+
local _key_0, _val_0 = xxxx
51+
_tbl_0[_key_0] = _val_0
52+
end
53+
return _tbl_0
54+
end)()
55+
_ = (function()
56+
local _tbl_0 = { }
57+
local _list_0 = {
58+
{
59+
1,
60+
2
61+
},
62+
{
63+
3,
64+
4
65+
}
66+
}
67+
for _index_0 = 1, #_list_0 do
68+
x = _list_0[_index_0]
69+
local _key_0, _val_0 = unpack((function()
70+
local _accum_0 = { }
71+
local _len_0 = 0
72+
for i, a in ipairs(x) do
73+
_len_0 = _len_0 + 1
74+
_accum_0[_len_0] = a * i
75+
end
76+
return _accum_0
77+
end)())
78+
_tbl_0[_key_0] = _val_0
79+
end
80+
return _tbl_0
2881
end)()

0 commit comments

Comments
 (0)