random idea that static dispatch enables (not saying we should or shouldn't do this, just an idea):
.0, .1, etc.) with methods (e.g. .get_0(), .get_1(), etc. - or some other name)|x| x.0 - in the static dispatch world, we already have a type for |x| x.get_0() so that wouldn't need special handling() in the language if we don't want it (we could keep {} as our "unit" type)() -> Str is actually a zero-arg function, because () is no longer a type (or a value), so it could be used exclusively and unambiguously to mean "a function of zero arguments" - which would have nice symmetry with how they're called, e.g. with foo()separately (also not saying this part is or isn't a good idea either), that would mean that if we wanted to, we could do the ".( means partial application" idea from #ideas > static dispatch - partial application syntax by having "partially applied function" be a valid type (since that requires having a first-class concept of 0-arg functions)
If this means I can stop working on fixing mono bugs with (), I'm here for it /s
I really think having zero-arg functions is a must-have for Roc
it definitely is the most obvious design
And parens make a lot of sense for notating functions
Tuples aren't that important in the scheme of things
So if we can make them usable in some other way such that parens can handle arg notation, then Roc looks more consistent and we don't have to use 3 different kinds of syntax sugar as a stopgap
well as discussed in #ideas > ✔ Do we need tuples? they're important enough to be worth having in the language, and it's frequently annoying if the only way to get values out of them is to destructure them :sweat_smile:
I'm all in on this
but yeah, static dispatch means we can simplify them I think
Yes, we need them
I really like the idea of types and values looking more similar
get_results! : () => Result(List(U64), LoadErr)
read_file! = ||
res = load_results!()?
Ok(res.transform())
That's not explicitly proposed here
Though this moves us in that direction
ah, I think someone brought that up at some point
Yep, let me find the thread
I don't have strong feelings about it (both ways look fine to me), but feel free to start an #ideas thread on it!
I know List<U64> is the most mainstream, but I do think that looks significantly worse than either (List U64) or List(U64), especially once you end up in >>> territory
Yep, I'd be pushing for List(U64)
Scala uses List[U64] as I recall, but we already use [ ] for something else
That's how tags work now anyways
looks like Gleam uses List(U64)
So it's just an extension of that
so maybe we could see how Gleam folks feel about it in practice? I don't know of any other languages which use that syntax
They have a Discord, or we could ask here?
I'll start that thread, anyhow
good to get these things sorted out one way or the other prior to 0.1.0 :big_smile:
Yep, I guess Syntax Season just got Punxsutawney Phil'ed!
there's no :groundhog: so I guess :hedgehog: will have to do
This sounds reasonable. I honestly feel like tuples are less important than originally proposed:
Vec3 type, but isn't a win for a Matrix type. (And you can't use them to make any sort of generic or flexible matrix)I still think they are pretty fundamental for returning multiple things and certain cases where records are too verbose, but otherwise, I feel like they don't add value to the language.
another neat thing: we could automatically give tuples .map_0() and .map_1() as well - I've used things like Tuple.mapFirst in Elm before
Just a question since there is renewed scrutiny around SD (and we don't know how it will go eventually anyway), but regardless of what happens - it still makes sense for a language with effectual functions to allow effectual functions to have zero args - and therefore a way to annotate that, correct?
I agree, yeah
Have you talked about allowing multiple return values? If the main reason for tuples is returning multiple values, then maybe supporting it directly is even better.
I really hate, that zig does not support multiple return values. Multiple return values is an important feature to support webassembly. There are things, in the webassembly world, that zig does not support because of this. They have an issue where there discuss to support it.
I don't think that the c-abi is a problem. This could only be a problem for functions provided by the platform to the host or effects defined by the platform. App code does not have to support c-abi. A platform knows, which abi it wants to support. If a platform wants to return multiple values to the host with c-abi, it can do it in a record, which has (nearly) the same memory layout then tuples. (Records order the fields, so it would not be possible to create a type like (U8, U64) .)
I don't say, that tuples should be removed from Roc. I want to say, that multiple return values is not a strong argument to keep them. I made the experience, that records are superior to tuples and the only reason I use tuples is because I am lazy.
From Richard's recent thread in #ideas > Result.map_ok, here are two code examples showing the difference between tuples and records:
params : Request -> List (Str, Str)
params = |req|
req
.path()
.split_first("?")
.map_ok(.after)
.with_default("")
.split_on("&")
.map(|param|
when param.split_first("=") is
Ok({ before, after }) -> (before, after)
Err(NotFound) -> (param, "")
)
params : Request -> List (Str, Str)
params = |req|
req
.path()
.split_first("?")
.map_ok(.get_1())
.with_default("")
.split_on("&")
.map(|param| param.split_first("=") ?? (param, ""))
For those APIs where the output values are made obvious by the function name and return type, tuples are less noisy.
So as you probably agree, something like tuples should probably remain in Roc, though I'm with you that records are always more descriptive
But I think you're right that we should consider allowing multiple return values in place of tuples, even after all the discussion we've had on the subject
Tuples seem good for:
when expressionI think if we supported arrays in Roc, then all of a sudden tuples are much closer to a full type system feature that could instead be a syntax nicety
However, I don't know how to support something like
when (left, right) is
(Blue, Green) -> ...
without adding lots of little tools that the singular addition of tuples doesn't handle
Sam Mohr said:
Tuples seem good for:
- Doing math with something that looks like an array
This almost never happens in practice. I think it is too niche/unergonomic to really be consider a benefit.
I do totally agree they are awesome for multiple return values and pattern matching.
Last updated: Jun 16 2026 at 16:19 UTC