TLDR: !? _is_ silly, but that could be spun into a good thing if we tried. If so, it could re-open it as a technical solution. This is a discussion of the branding of it, not the technical merits.
Background:
The purity inference proposal has stumbled a couple of times onto solutions which lead to a lot of !? in the code, as a composition of a ! operator and a ? operator. These might be good technical solutions, that are understandable, composable, and easy to use, but Richard has said:
maybe it's just me, but personally I find
!?so ridiculous-looking that I can't even imagine wanting to get up on a stage and show code on a slide that includes it. Or write a blog post about it. I dislike it so much that I think it would make me feel ashamed to try to promote the language. https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/Purity.20inference.20proposal.20v3/near/468421163
I also know Richard said
!?is not an alternative we should spend time discussing because at this point I just can't imagine a world where that ends up being the final design https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/Purity.20inference.20proposal.20v3/near/468421742
so feel free to close this topic. But this is specifically not opening discussion of whether it's a good technical design, _unless_ the branding objection is dealt with first.
The idea:
I don't think being silly has to be a deal breaker. Whimsy is good! It could become a recognizable symbol of the language. People could say "Oh, I've heard of Roc, that's the language with the !?, right?", the same way that people know Lisp as the language with all the parentheses, or APL as the one with all the symbols. Those are both kind of silly and recognizable but also very effective parts of those languages.
When reading and writing code, for people familiar with the language, it could become a little bit of excitement and fun, a bit of a laugh in an otherwise emotionless industry. It's so memorable that it'd guide people into using the idiom. I already feel this whenever I see a ! in roc code, I think do the thing! and it makes me smile. We could get a lot of fun use out of the :interrobang: emoji.
For people new to Roc, and in conversation and slides, there's obviously a little bit of "what's that punctuation doing!?" feeling, but I don't think it's _embarrassing_. I think it'd be easy enough to brush off as "haha, yeah, I know it looks silly, but it's just doing the ! operator and then the ? operator. If wielded well, it could even be a drop of comic relief in a dry conference talk, or a memorable milestone in a long tutorial. There's a bump in the learning curve, and a bump in the weirdness budget that would need to be evaluated. But I don't think the silliness itself is an insurmountable obstacle. (That said, I'm not the one giving talks or writing tutorials.)
There's plenty of examples of similar situations in other languages. TypeScript has !. and ?.. Whatever Haskell has going on with its infix operators is even weirder (they're also confusing, but that's an unrelated issue) and they're so iconic that >>= made it into the logo. If a language defined functions with the keyword fun, I'd think "heh, that's fun, but not unusual".
I guess in summary, having !? in code is silly, but it's fun and memorable and could become a positive for the language. If !? might be a technically good solution, then it doesn't have to be ruled out based on the appearance alone.
Yeah, I personally don't mind it at all and like that it is simple and clear. I think it would be totally fine. I think it at least has enough merit to be worth trying.
I actually do like how !? appears :) and it makes sense to me how that composes.
I'm wondering: how do others feel about this? Am I alone in disliking it?
I think after reading almost one hundred "pages" of design docs on these concepts, I'm pretty familiar with what ? and ! individually translate to. With that knowledge, I find it easier to consider ? as "defer an error" and ! as "invoke an effectful function" individually, because I almost always prefer simple concepts that are transparent to the developer, even if they are more verbose. And this is only one more character.
Maybe I'd bias away from !? if I didn't have the familiarity with the underlying mechanisms, but I am, so it's hard to say. I think asking uninvested/Roc-unaware devs what they think would be really helpful here to avoid the Abilene paradox, though it may be hard to get people into the right mindset to give useful answers.
Really, the thing I want from ! is a demarcation of effectful code. I think there are probably other simple ways to do that than !, and we should avoid biasing towards exclamation marks just because they're what we were already using. (Though I know other languages have done ! before, like Ruby)
I'd also be less happy, but still happier than a polymorphic !, if we did away with ! and made it implicit like in v2 of the proposal. I'm more okay with this since we now have => to notate function bodies that are effectful.
An alternative we could do in the style of end-of-line ? is to use an @ or # prefix for effectful functions. I think @echo "hello" is sufficiently aesthetic, maybe less so in the qualified case, a.k.a. @Stdout.line "hello" or Stdout.@line "hello".
But it composes well with ?: @readFile? "file.txt"
I will say, I just asked my Zig-aware, Roc-unaware coworker what he thought about !? and he said, "No, that's awesome. You'd say, like, printLine!?" and then laughed.
I think another option would be to replace ? with a Zig/Swift-style try keyword
try readFile! "file.txt"
We are already pretty keyword-focused, it would be in line with that
Fwiw zig has !? as a not-uncommon occurence in code, being used to indicate an error union with an optional child (E!?T or !?T specifically in the return type), so from my pov it isn't too odd or really even that silly
I do think Zig is more willing to look "jank" than Roc, because it is aimed at C developers :sweat_smile:
I appreciate the effort Roc puts into style. But I agree with you @InKryption that this isn't that crazy
Agus Zubiaga said:
try readFile! "file.txt"
Or the opposite :big_smile:
do readFile? "file.txt"
:stuck_out_tongue:
do try readFile "file.txt"
I think either of these options could work just like how dbg has been made to be pipeline-able:
jsonContent =
File.read! "text"
|> try
|> Json.decode
Oh, good point!
I think if we have to pick between ! and try, and ? and do, I'd bias for ! because that's the more used syntax, probably.
I think I prefer try over ? in general:
try with errors Result valueI know it would make scripts more verbose, but I’m personally fine with that
I'm somewhat coming around to this... though I still think !? is fine
I don't like !?, I think it looks confusing. I like the idea of just using a keyword like try. It's very obvious and less magical.
I don't have really strong opinion here or much experience, just worried that operators can be a little confusing unless they are really common.
Maybe it's time I suggest a not keyword, then...
Many languages have obscure or inexplicable symbol combinations at first glance (or else the verbosity that comes from lacking much use of symbols, such as in cobol).
Haskell _certainly_ falls into the category of confounding use of symbols, but nothing I've seen in Roc or serious proposals even approaches that level of potential for confusion.
A serious, well designed language should ideally have at least a few important priorities w.r.t. use of symbols:
! naturally indicates a directive or potential danger. ? naturally indicates something that is conditional or needs to be checked. As long as these properties hold, then it's a respectable, justifiable/defensible design, and I don't think there's anything particularly silly or embarrassing about it. If being introduced to Roc for the first time with that design on a slide, I would personally be in the mindset of thinking about this mechanically, and quite far removed from thinking about code as though it were a series of natural language sentences.
Sam Mohr said:
I think either of these options could work just like how
dbghas been made to be pipeline-able:jsonContent = File.read! "text" |> try |> Json.decode
We should probably allow for pipeline-specific desugaring for try, I think bare try in a pipeline doesn't look very good:
jsonItem =
try Http.get! "http://api.com"
|> try Json.decode
|> List.get (try Str.toU64 strIndex)
At this point I think we should try !? to see how it ends up in practice. It is by far the simplest composable solution. We can let it run for a bit and see the feeling from users both old and new.
If it's a problem, we can try try or whatever else
I agree. !? Seems like a fairly lightweight solution syntactically and conceptually. I really appreciate that the rules behind it are not overly complicated
Richard Feldman said:
I'm wondering: how do others feel about this? Am I alone in disliking it?
More dislike than like.
Isaac Van Doren said:
I agree. !? Seems like a fairly lightweight solution syntactically and conceptually. I really appreciate that the rules behind it are not overly complicated
They are. Too much sugar, questionable 'benefit'.
Backpassing is ok. Just because something is new or unfamiliar doesn't automatically mean that it's bad, or that your language has to look like rust (cuz rust is a meme right now...)
The issue with backpassing is that newcomers to Roc have multiple times specifically mentioned that it was the hardest feature for them to figure out
So if it was just a general anxiety that led to backpassing being deprecated, I'd agree
But it's specific evidence
Now, luckily for us, the try keyword seems like a very beginner-friendly mechanism that does the same thing as ?
Sam Mohr said:
The issue with backpassing is that newcomers to Roc have multiple times specifically mentioned that it was the hardest feature for them to figure out
I assume newcomers want to learn something new?!? Why would I be interested in something that is the same that I already have/use?
And once you figure it out it makes a lot of sense and is very powerful.
New is good! I got into Roc because of the builder pattern
Super cool feature
But Roc is hopefully gonna be a language that's good for teams, where you have people jumping into Roc codebases that may not even really know the language
So how can we make a language that is good for people that want to be there, but also those that don't know what they're doing?
It's a hard optimization problem, because we end up taking away really useful tools
Like backpassing
Or the ability to implement Monads
That's why Roc adds new features to try them out, and then drops them later if they make the resulting language worse
Sam Mohr said:
But Roc is hopefully gonna be a language that's good for teams, where you have people jumping into Roc codebases that may not even really know the language
Documentation, particularly for platform writing, has to be down first. I know "documentation" is boring and not fun, but it's vital for building trust. And trust is needed for growth...
There are a lot of ways to skin this cat, can we find the simplest and smallest set of tools that let us do that
We agree that docs are SUPER important
We are just prioritizing ideation of the right feature set for the language over investment in stuff like docs, because we only have so many devs and we'd rather not get bogged down by docs that will go out of date quickly
But
That doesn't this is the right approach. We could definitely do a better job of giving docs and change logs and all that
Anyway
The question I had, out of curiosity, was why you didn't find much benefit in something like ?!
Do you not like ?, or !, or both?
Would you prefer a tool that can do what ? does and more?
Would love to hear why you're not a fan, this is a really big discussion point right now!
Sam Mohr said:
The question I had, out of curiosity, was why you didn't find much benefit in something like ?!
I just read the discussion about try. I think it's much preferable over syntax diarrhea.
"Left/right association"/"order of operation" in particular is a problem I have with ?!!?!?
Seeing multiple of them chained like that would never happen
You wouldn't even be able to see ?! without an extra pair of parens.
So it would just be !, ? and !?
Last updated: Jun 16 2026 at 16:19 UTC