Stream: ideas

Topic: more keywords in syntax


view this post on Zulip dank (Feb 26 2023 at 22:05):

Ayaz Hafiz said:

there are some examples of using abilities here

how sure are you all about that syntax?
is it (in pre 0.1 terms .. ) final?
I showed it to some people too, has/ :=/@ seem to be a source of confusion

view this post on Zulip Brendan Hansknecht (Feb 26 2023 at 22:17):

I think at least the wording is already planning to change due to has being unclear especially when used in multiple contexts.

view this post on Zulip Brendan Hansknecht (Feb 26 2023 at 22:19):

As an extra note, I would assume that := and @ will almost always seem confusing to people not familiar with roc. They are not specifically related to abilities.

view this post on Zulip Brendan Hansknecht (Feb 26 2023 at 22:20):

They are for opaque types which is not really in other languages. So kinda something you just have to learn that is unique to roc.

view this post on Zulip Brendan Hansknecht (Feb 26 2023 at 22:20):

Though of course the syntax could theoretically change.

view this post on Zulip dank (Feb 26 2023 at 22:24):

yea I know and can empathize the rationale.
but perhaps we could come up with something cleaner
that as a bonus would also not make some folks say "ew walrus" (I can see the hackernews comments coming a light year away)

view this post on Zulip Brendan Hansknecht (Feb 26 2023 at 22:27):

optimizing for hackernews comments seems pretty low priority to me, but yeah, feel free to recommend other syntax or open discussion in #ideas

view this post on Zulip Brendan Hansknecht (Feb 26 2023 at 22:28):

Always nice to improve syntax where possible and help make the language easier for beginners.

view this post on Zulip dank (Feb 26 2023 at 22:35):

lol I was kinda kidding but yea well the underlying thing to notice is when the toxicity of said comments might reflect an actual painpoint (disguised by orange) for someone that just sees the lang for the first time
but yea I think we agree here

view this post on Zulip Ayaz Hafiz (Feb 26 2023 at 23:48):

+1 on changing the abilities syntax and trying to optimize for developer experience. I would also caution against trying to optimize for HN or other forums. the vocal majority is not representative, and forums are often not conducive to understanding the whole context. Of course, in isolation features should feel pleasant regardless

view this post on Zulip Richard Feldman (Feb 27 2023 at 02:25):

I definitely think the abilities syntax should change

view this post on Zulip Richard Feldman (Feb 27 2023 at 02:25):

I'm open to changing the syntax for opaque types, but I don't think there is an obvious better alternative

view this post on Zulip Richard Feldman (Feb 27 2023 at 02:26):

on the other hand, with abilities we've discussed multiple alternatives we think are better, and the tricky part is picking a specific design :laughing:

view this post on Zulip Anton (Feb 27 2023 at 10:51):

An opaque keyword could work:

opaque Username = Str

Instead of:

Username := Str

view this post on Zulip Anton (Feb 27 2023 at 10:53):

Sidenote: I've also come to realize that "the vocal majority is not representative" is a valuable life lesson :)

view this post on Zulip Joshua Warner (Feb 27 2023 at 20:21):

FWIW, I would love to move more in the direction of having keywords for both := and : (when used as an alias, not an annotation).

view this post on Zulip Joshua Warner (Feb 27 2023 at 20:21):

(which is to say, I like the suggestion above of opaque Username = Str)

view this post on Zulip Joshua Warner (Feb 27 2023 at 20:22):

Keywords are much more discoverable / searchable / etc

view this post on Zulip Richard Feldman (Feb 27 2023 at 22:12):

a downside of that is that now identifiers like opaque and alias become reserved keywords and can no longer be used in userspace

view this post on Zulip Richard Feldman (Feb 27 2023 at 22:13):

and yeah they're less discoverable/searchable but I think that's less of a downside for super common language primitives; people might not know what they mean when glancing at Roc code and not knowing Roc, but anyone who reads the tutorial will know what they mean right away

view this post on Zulip Richard Feldman (Feb 27 2023 at 22:13):

(contrast with ability for example, which is something I suspect most Roc users will use rarely to never - so discoverability/searchability is a bigger upside)

view this post on Zulip Joshua Warner (Feb 27 2023 at 23:27):

: is a bit more confusing since it's overloaded between type annotations and type aliases.

view this post on Zulip Joshua Warner (Feb 27 2023 at 23:27):

... but I digress

view this post on Zulip Ron Panduwana (Feb 28 2023 at 00:26):

Richard Feldman said:

a downside of that is that now identifiers like opaque and alias become reserved keywords and can no longer be used in userspace

perhaps they can be soft-keywords like in Kotlin?

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:29):

interesting! @Joshua Warner do you think a soft-keywords design would work okay in the context of a lexer?

view this post on Zulip Joshua Warner (Feb 28 2023 at 00:32):

Some keywords will need to be 'hard' - specifically, I think 'if' / 'else' / 'then' / 'when' / 'is' all need to be "hard" in order for the "blocks" idea to work out

view this post on Zulip Joshua Warner (Feb 28 2023 at 00:32):

(this is because we need to handle those specially, and allow indented blocks to come afterwards)

view this post on Zulip Joshua Warner (Feb 28 2023 at 00:32):

Anything that doesn't allow an indented block immediately afterward can be a soft keyword.

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:34):

hmmmm interesting!

view this post on Zulip Joshua Warner (Feb 28 2023 at 00:35):

opaque / alias would presumably come at the beginning of the line - so it'd be "annoying" if someone tried to name a function or local variable after those. You'd have to 'escape' such uses by e.g. wrapping them in parens.

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:35):

couldn't we disambiguate during parsing?

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:36):

e.g. opaque Foo and alias Foo is clearly a keyword usage because of capitalization, since opaque Foo = wouldn't be allowed

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:36):

also a b c = is a parse error, so all we need to do is read the next token after opaque or alias to see what it is (or if it's invalid), give or take comments I suppose

view this post on Zulip Joshua Warner (Feb 28 2023 at 00:37):

I think that's possible.

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:37):

so it's either opaque = or opaque : (assuming we've changed to alias for type aliases) for identifiers, and opaque Foo for types

view this post on Zulip Richard Feldman (Feb 28 2023 at 00:37):

and same for alias

view this post on Zulip Notification Bot (Feb 28 2023 at 00:41):

38 messages were moved here from #beginners > Ad Hoc Polymorphism by Richard Feldman.

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 01:06):

I haven't used kotlin or soft-keywords in general, but I think that just looks more confusing. Totally could be first look bias/lack of experience, but I like the idea of only having clear hard keywords.

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 01:07):

if opaque and alias are common keywords, I think it would be very strange to see them as variable names. I guess it is less jarring of an idea for uncommon keywords like ability.

view this post on Zulip Richard Feldman (Feb 28 2023 at 01:24):

yeah opaque seems like it could come up in graphics systems, and alias is a common term for a person's alternate name

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 01:29):

very true

view this post on Zulip Joshua Warner (Feb 28 2023 at 01:29):

Aligning those names better with what other languages use might help. e.g. something like private and type, respectively.

view this post on Zulip Joshua Warner (Feb 28 2023 at 01:30):

Then at least fewer programmers would expect to be able to use those as identifiers

view this post on Zulip Joshua Warner (Feb 28 2023 at 01:31):

... but the soft keywords approach is definitely workable, both in the current parser and the [possible/planned future] lexer[-based parser] - and seems much preferable to me to just using the :=/: symbols.

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 01:33):

I definitely currently prefer the symbols over soft keywords but :shrug:. I'm sure I would get used to either.

view this post on Zulip Ron Panduwana (Feb 28 2023 at 01:34):

If := is disliked, how about :: or :::

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 01:35):

Also, we could always go with slightly longer names if we want to reduce overlap and keep clarity. alias could be typealias or type alias

view this post on Zulip Ron Panduwana (Feb 28 2023 at 01:37):

typealias is better because quite often I need to have a variable/field named type

view this post on Zulip Joshua Warner (Feb 28 2023 at 01:42):

I like typealias. Very clear about what it is.

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 01:50):

do type alias and opaque type work? Not sure if they should have spaces, or be mashed to gather or other. I think both of those names are clear and due to being longer/2 words should make it so that soft keywords don't feel as strange. opaque, type, and alias used by themselves would be a variable. opaque type and type alias are the only form as a keyword.

view this post on Zulip Richard Feldman (Feb 28 2023 at 02:17):

that's interesting! Elm uses type alias actually

view this post on Zulip Richard Feldman (Feb 28 2023 at 02:18):

Ron Panduwana said:

typealias is better because quite often I need to have a variable/field named type

yeah I think in around half the languages I've ever used, I've wanted to use type as a variable name and have been annoyed that it was a reserved keyword :laughing:

view this post on Zulip Richard Feldman (Feb 28 2023 at 02:18):

a complaint I've heard people say about type alias in Elm is that it's verbose, but I do like that it's super clear

view this post on Zulip Richard Feldman (Feb 28 2023 at 02:19):

I think if we did type alias it would make sense to also do opaque type

view this post on Zulip Richard Feldman (Feb 28 2023 at 02:19):

another option is type-alias and opaque-type

view this post on Zulip Joshua Warner (Feb 28 2023 at 02:22):

From a lexer perspective, I'm worried about hyphenated keywords making things unnecessarily complicated.

view this post on Zulip Joshua Warner (Feb 28 2023 at 02:23):

Also, hyphenated keywords are pretty unusual I think (outside of lisps, I mean...)

view this post on Zulip Joshua Warner (Feb 28 2023 at 02:25):

Specifically for anything that we're considering a 'hard' keyword, I'd like to make sure those are always identifiers (by which I mean, they _would_ be valid identifiers if they weren't considered keywords).

view this post on Zulip Joshua Warner (Feb 28 2023 at 02:29):

And, for 'soft' keywords, they ideally need to be recognizable as such at the parser level from tokens - which is to say, they're still recognized if there's some non-newline whitespace inserted - so opaque-type needs to be tokenized as IDENT, UNARY_MINUS, IDENT - and that in turn means that opaque -type needs to have the same semantics.

view this post on Zulip Joshua Warner (Feb 28 2023 at 02:32):

(It's definitely _possible_ to do hyphenated keywords in the lexer - but that adds to the list of weird hax that tend to cause problems later)

view this post on Zulip Brendan Hansknecht (Feb 28 2023 at 02:47):

Does anything else allow hypens in general? I think it would just feel inconsistent with the rest of the language to throw in hypens just for 2 keywords.

view this post on Zulip Luke Boswell (Feb 28 2023 at 07:23):

Some previous discussion on record syntax

in Roc today:
- always, what comes before = is a pattern
- always, an identifier followed by a : is a record field declaration
- always, an identifier followed by a blank space and then a : is a type declaration

Option 1 - Use = for both type alias and opaque type

# Type annotation
amy : { firstName : Str, lastName : Str }
amy = { firstName: "Amy", lastName: "Lee" }

# Type alias
type alias Musician = { firstName : Str, lastName : Str }

amy : Musician
amy = { firstName: "Amy", lastName: "Lee" }

# Example opaque type definition
opaque type CodePoint = U32
opaque type Json = {}
opaque type Decoder val fmt = List U8, fmt -> DecodeResult val | fmt has DecoderFormatting

# Example type alias
type alias App state initData = {
    init : DecodingResult initData -> state,
    render : state -> Html state,
    wasmUrl : Str,
}

type alias Html state = [
    None,
    Text Str,
    Element Str Size (List (Attribute state)) (List (Html state)),
]

Option 2 - Use : for both type alias and opaque type

# Type annotation
amy : { firstName : Str, lastName : Str }
amy = { firstName: "Amy", lastName: "Lee" }

# Type alias
type alias Musician : { firstName : Str, lastName : Str }

amy : Musician
amy = { firstName: "Amy", lastName: "Lee" }

# Example opaque type definition
opaque type CodePoint : U32
opaque type Json : {}
opaque type Decoder val fmt : List U8, fmt -> DecodeResult val | fmt has DecoderFormatting

# Example type alias
type alias App state initData : {
    init : DecodingResult initData -> state,
    render : state -> Html state,
    wasmUrl : Str,
}

type alias Html state : [
    None,
    Text Str,
    Element Str Size (List (Attribute state)) (List (Html state)),
]

view this post on Zulip Anton (Feb 28 2023 at 10:54):

I'm not a fan of the space in between, we already use spaces as separators between arguments so this seems confusingly similar.
My preference would go to typeAlias and just opaque. My reasoning for just opaque is that if you're writing "nice roc" you'll be using Opaque, those using a bool can also simply use isOpaque.

view this post on Zulip Jacob (Aug 18 2023 at 15:45):

Lean also uses opaque for example

opaque CodePoint : UInt32
opaque Decoder [DecoderFormatting val] : List UInt8  (fmt  DecodeResult val)

Last updated: Jun 16 2026 at 16:19 UTC