Tying in from a couple topics...
Richard Feldman said:
one of the things I like about having a word instead of punctuation (e.g.
has,supports,implements) for the token that appears before the abilities is that it reinforces that these are not about classification
Anton said:
I think
\is the only/main problem.
It is kind of a pain on azerty.
Since we're evaluating symbols vs keywords in a few places (or debating which keywords to use)... one of the things that has long struck me as [subjectively] inconsistent about the grammar of Haskell family languages, but particularly Elm and Roc, is the non-committal adherence to both a symbol-oriented syntax for much of the language, yet a keyword oriented syntax for the rest of the language: several other languages I'm familiar make a more pronounced choice in one direction or the other.
To be sure, what follows is not intended to be a debate nor a specific suggestion, nor a value statement at all, but merely an observation (which I believe may impact the learning curve and intuitiveness for those coming to Roc from outside the Haskell family).
For example, in a C family language, an if conditional might be disambiguated from the guarded expression/statements by mandatory parentheses or a mandatory curly-braced block (favoring symbols over keywords), while Roc uses then for disambiguation (favoring keywords over symbols). In contrast, Roc uses \ to introduce functions and : to introduce declarations (favoring symbols over keywords), while another language might use def, fn, type, etc for the same purpose. Imports are also a bit curious: in Python you'd have a pretty explicit from module import a, b, c, which requires little explanation, whereas in Roc it'd be packages { pf: "..." } and imports [A.B.{ X, Y }] (a mix of different symbols and literal-like syntax, though I'm assuming actual record and list operations don't work here as might be implied by the syntax).
Python tends to reuse its keywords (as, from, in, and is show up in many places in the grammar), and thus gets a lot of value in exchange for the variable names you are not allowed to use; in Roc, most keywords seem to be used in exactly one part of the grammar. Keywords (and more generally any single-use syntax) carry a cost, and a language arguably has a budget it can expend before it either has so many keywords that they make variable name choice tedious, or requires frequent reference to write code (particularly each part of the grammar is "bespoke" and doesn't have intuitive/predictable themes and overlaps with other parts of the grammar). I'd reference all the ways and places you can destructure in Elm, especially in conjuction with as, and the subtle ways those forms might differ based on where they're used (e.g. case expressions vs function params), as an example of surprising and, unfortunately, unintuitive grammar: without the cheat-sheet, and due to the lack of a formal language specification, I could have actively used the language for years without stumbling upon more than just basic destructuring capabilities, because there are just so many permutations that don't see regular use (as an aside, that cheat sheet felt to me more like a "intrepid language explorers discovering emergent syntax" rather than necessarily deliberate/holistic design you can merely learn from official reference material).
In Roc's case, there's a bit of co-redundancy regarding several current and considered keywords: if we're thinking about where, then when could pretty workably be changed to where instead for pattern matching (it could potentially read as well as when, and would have more value-per-keyword, presumably without introducing ambiguity). Similarly, has would probably have more opportunities for reuse than implements. If Roc were to favor expressing itself more through keywords than symbols, than fn or some other keyword to introduce functions, and a more spelled-out import syntax, may be a self-consistent outcome. Conversely, if Roc were to favor expressing itself more through symbols than keywords, where and when could perhaps be released to be used as variables, as certain types of programming (scheduling, geolocation, database query construction, etc) could benefit from being able to use those terms.
As another aside, do we have an easy way to assess overall grammatical overlap and simplicity vs complexity (such as via a BNF spec)?
We have a peg grammar. Note that it does not yet contain rules for abilities.
Interesting. I actually find the limited but unique keywords quite nice. Languages that use the same keywords in many ways just hurt learnability/readability. Languages that use too many symbols do the same, probably worse. Anything that is very common, readable(i know pretty subjective) and relatively easy to understand can be a symbol. Anything that is less common, would be useful for formatting/always pronouncing can be keywords.
Not say Roc nails this line, but i think it is a reasonable line to target.
I say all of that while enjoying languages like APL/BQN (king of symbols) and Python (as mentioned quite word heavy).
Though, I still find a lot of Haskell (symbol heavy for grammar with lots of ways to write things terse) hard to read :joy:.
Sam Mohr said:
If we move towards keywords over operators for the logical ops like
andandor, we may lean away from adding more symbols.
I've seen this reaction quite a few times now, so I don't know where to react but I'll do it here. It is not directly related to bit shifting though so if this becomes a discussion, maybe it should become its own thread.
Basically the comment (and others) have said we are moving away from symbols towards keywords. I feel like we have been introducing a little more keywords but that is it. I don't feel like symbols over keywords is always good. If it was, we wouldn't use symbols for + and -.
Also, I remember a long time ago, Richard explicitly wanting to keep the number of keywords low, so they can be used as variable names. This is why we have the : and := for type definitions, and not e.g. type and opaque type. Just my 2 cents. I think we should be careful with introducing keywords just like that.
But like I said, this has little to do with bit shifting anymore. Sorry for the rant :sweat_smile:
A message was moved here from #beginners > Bit shifting operators? by Brendan Hansknecht.
Cause I think this is an interesting discussion that would sidetrack the other thread. Thought I would throw this into ideas for discussion
For me, I think an important note on keeping keywords minimal is that some keywords are actually terrible variable and functions names. and and or are terrible variable names, but with a correct context or scope, they are totally reasonable function names
For example, in a SQL dsl, it would be great to just use and and or as functions
So it is very important to keep that in mind when deciding on keywords.
For me personally, I have seen it help a number of beginners in python to see and and or as actual words. As such, I think they would really help make roc more friendly.
That said, roc is lighter on booleans and uses when ... is pretty often, so it is less important in roc to have and and or compared to python. None the less, it is still definitely common to see them
But in general when thinking about keywords, it is important to pull back and think about what context we are blocking the words to be used in
I think that having and and or would probably block all functions and variables with the names and and or in all contexts. They are the most restrictive kinds of keywords. Other keywords, like exposing, have almost zero effect around where the word exposing can be used. So exposing is a very lost cost keyword. It add essentially zero restrictions
and, or, try are all expensive keywords. Someone may want MyModule.try/and/or. They are all great function names.
Last updated: Jun 16 2026 at 16:19 UTC