I'm curious: will Roc ever grow list comprehensions? I wrote a Python script yesterday and it was like giving an old friend a high five.
(some Rust-Iterator-like concept may be better though.)
I think that most usage of list comprehensions is covered already by Roc's backpassing capabilities. (and List.joinMap)
Though I guess that you'd have to be explicit with the pattern-matching (and handling of values not matching the pattern)
I find Scala's for-comprehensions even more expressive than Python's list-comprehensions. Both are more expressive and clearer than nested loops. It would be syntactic sugar over iterators that turns for loops into expressions, but would require a flat_map function in addition to map. I am not sure what is the equivalent to flat_map in Roc. Anyway, I also think it would be neat if for-comprehensions make it into Roc.
@Qqwy / Marten I'd be curious if could you share an example of something that you'd use a list comprehension for in Python and how you'd do it using backpassing in Roc.
Backpassing is gone from the language by now. It was mainly used for tasks and error handling, but they have been subsumed by effectful functions and the ? operator respectively.
I question whether list comprehensions align with roc's philosophy as Roc tries to stay a small language with fewer primitives. Allowing things to be done "one way" is a desirable outcame (but that "one way" has to be a pleasant experience). That's just the general impression I've gathered from lurking around in these chat rooms.
We don't have a flat_map equivalent but we will probably add it if there is sufficient demand. I also noticed we don't have List.flatten, that feels like a no-brainer to add, what do you think @Richard Feldman?
# expect [[1, 2], [3], [], [4, 5]].flatten() == [1, 2, 3, 4, 5]
flatten : List(List(a)) -> List(a)
yeah we should add List.flatten for sure! :+1:
arguably it should be called join but probably flatten is the most intuitive name
Not a strong opinion, but I would expect flatten to be recursive, for example [[1,2],[3,[4,5]],6].flatten() == [1,2,3,4,5,6], while I expect join to be just one level deep: [[1, 2], [3, [4, 5]], 6].join() == [1, 2, 3, [4, 5], 6].
In Kotlin, Scala and Rust, flatten is one level deep. In Ruby and Clojure flatten is recursive.
yeah that's a solid argument for join :+1:
By the way, all elements of a List need to have the same type, so [[1, 2], [3, [4, 5]], 6]is not a valid list.
If I am not mistaken it is not possible to write one function which can recursively unnest a list of nested lists with an arbitrarily deep nesting in Roc.
Richard Feldman said:
yeah that's a solid argument for
join:+1:
I've named it join in the issue
I find flatten more intuitive personally. Both because I associate join with database-like joins first and foremost. But join is also synonymous with concat, which is already used to append one list to another. Elm uses both concat and append for these operations, and even after years of using them, I can never remember which is which. I much prefer flatten because it removes this ambiguity.
Last updated: Jul 23 2026 at 13:15 UTC