-
Notifications
You must be signed in to change notification settings - Fork 62
return more than one value from a for-comprehension #3966
Comments
It's called
Interesting. So basically you're providing |
[@FroMage] I love how you can say |
[@quintesse] Be careful with what you say, he might just rename |
[@gavinking] Oh I realize that, but then I would have to find a new name for the arguably deeper and more basic operation that is currently called |
[@gavinking] OK, so this issue us actually way more important than I had realized. For #3913, we need something almost exactly like this. Unfortunately, the syntax that makes sense for #3913 is this: Div {
for (sect in sections) {
Title(sect.title),
Text(sect.text)
}
} Not, as proposed by @FroMage: Div {
for (sect in sections) *{
Title(sect.title),
Text(sect.text)
}
} But the first syntax has a huge problem. It naturally means a comprehension producing iterables! Now I'm regretting not having required an extra punctuation character in our comprehension syntax, for example: [ for (i in 1..10) : i^2 ] That would have spared us from this ambiguity :-( |
[@gavinking] FTR, today you can write this as: Div {
*expand {
for (sect in sections) {
Title(sect.title),
Text(sect.text)
}
}
} But this involves a whole extra level of nesting, and two rather technical constructs, the |
[@FroMage] I think this will become part of a bigger debate over the syntax, because I presume people will also want to be able to do: Div {
for (sect in sections) {
Title(sect.title),
Text(sect.text)
},
for (para in paragraphs) {
Title(para.title),
Text(para.text)
},
if (needsSomething) {
Text(something)
}
} |
[@gavinking] That's #3913 of which this is just a part. |
[@gavinking] So there is a workaround, with what we have today. A framework could define a Div {
for (sect in sections)
Fragment {
Title(sect.title),
Text(sect.text)
}
} That's not perfect, but I think it's OK. |
[@gavinking] Well, hrm, @drochetti is already way ahead of me here and he actually already supports almost the same idea in Div {
for (sect in sections) {
Title(sect.title),
Text(sect.text)
}
} The downside of that is that |
[@gavinking] A further alternative would be to put the Div {
*for (sect in sections) {
Title(sect.title),
Text(sect.text)
}
} With: Div {
for (sect in sections) *{
Title(sect.title),
Text(sect.text)
}
} |
[@gavinking] We should go with the prefix |
So, I've been thinking about this since I first found Ceylon, and I think I've figured out a pretty good, simple, intuitive, and regular syntax for this. The idea is to have a syntax for both "expressions" and "multi-expressions". Consider:
With this approach, you would be able to have a comprehension that returns multiple values by either using the spread syntax or by using parentheses. For example: function expand<Element>({{Element*}*} streams) => {for(value stream in streams) *stream}; value div = Div{for(section in sections) (Title(section.title), Text(section.text))}; Now, as an addendum to the idea, something interesting that could be done is to allow someone to define condition lists in terms of multi-expressions. That is, consider the following extension to the syntax of
And now look at how simple the syntax for
This also helps fix the problem posed in #4540, by simply allowing people to write the following: if(!(exists foo, exists bar, hours < 24))
{
return(null);
}
return(foo + bar + hours); It's interesting to note that those conditions would still be only allowed inside value foo = exists bar; // syntax error value foo = [exists bar]; // semantical error |
+1 for figuring this out. When I get a chance, I'll link to real world code examples where this would help. |
[@FroMage] I know we can do that with something that flattens the resulting comprehension afterwards, but it could be useful to support "returning" more than one value from a comprehension:
Where I reuse the
*
operator to spread more than one value in the comprehension.[Migrated from ceylon/ceylon-spec#860]
The text was updated successfully, but these errors were encountered: