cursorless-dev / cursorless

Don't let the cursor slow you down
https://www.cursorless.org/
MIT License
1.12k stars 78 forks source link

Add keyword for alternatives in a match construct #579

Open wenkokke opened 2 years ago

wenkokke commented 2 years ago

edit @pokey:

As discussed in https://github.com/cursorless-dev/cursorless/issues/579#issuecomment-1161627378, we'd like to proceed as follows:

Original

There currently is no keyword for selecting alternatives in a match construct. Examples of match constructs are:

We probably want three keywords:

Unmodified pattern and case should probably to the scopes relative to the named mark or cursor, i.e., pattern refers to Alt1 if the mark or cursor is in either Alt1 or exp1, and similarly for case.

pokey commented 2 years ago

Good stuff thanks for filing. A couple thoughts:

wenkokke commented 2 years ago

Patterns and values are rather different and merging them might let to very confusing selections...

Are you suggesting that "arg" matches the matched value when the cursor is on "match"? There could be arbitrarily nested function calls in x, so having a keyword that jumps directly to the top of the match construct might be extremely useful?

pokey commented 2 years ago

Let's talk this one out when we discuss the haskell stuff. I like to merge when I can to keep vocabulary down but when it doesn't make sense I'm always happy to add another scope type

purpleP commented 2 years ago

I think it makes more sense to discuss this while we’re working on Rust support as rust pattern matching capabilities and syntax is more complex than that of Haskell. And it’s such an integral part of the language that I don’t see much sense adding rust support without pattern matching support.

auscompgeek commented 2 years ago

We should probably think about how we can make match arms consistent with case arms. Ref: https://github.com/cursorless-dev/cursorless/issues/247

purpleP commented 2 years ago

That’s probably a technical limitation, but if it isn’t I would actually allowed each language to define it’s own scopes instead of trying to define a set of common ones and having languages where not all of them are defined. Sure, there’s a lot of commonalities between PLs, but there’s also a lot of differences which would be quite hard to model properly. IMHO it doesn’t even worth trying to do this.

pokey commented 2 years ago

General philosophy

That’s probably a technical limitation, but if it isn’t I would actually allowed each language to define it’s own scopes instead of trying to define a set of common ones and having languages where not all of them are defined

Yes, today all languages share scope types, and that is in fact a technical limitation that we'd like to remove. Unfortunately, we're dependent on Talon RPC to make that happen, so it's tough to say when exactly we'll be able to move past that limitation

However, even once we are able to have language-specific scope types, consistency is still important. For people who work in multiple languages, consistency is quite helpful. It's one of the nice things about using knausj, for example. You can use roughly the same set of commands to work in many languages. I don't think we need to be dogmatic about consistency, but I'd argue that we should only drop it if we have a good reason to do so.

Match statements themselves

A case for consistency

More concretely, in this case, I would argue that match statements and case statements are conceptually similar enough that we should align the scope types across languages. They have the same elements in all the languages we're talking about here (Python, Typescript, Haskell, and Rust):

In an attempt to reduce cognitive load, I would push for using the same scope types for each of these across languages.

Proposed scope types

I would argue for the following:

In pictures

Following your great example, @purpleP, I've taken some screenshots 😊

"subject" / unsupported
image
"branch"
image image
"name" / "key" / "condition"
image
"value"
image image
"inside branch"
image image

Timeline

And it’s such an integral part of the language that I don’t see much sense adding rust support without pattern matching support.

I think that is fine, as long as we have a fast follow-up PR that introduces it for more languages. I am a bit hesitant to introduce a new scope type that isn't supported by most languages. The follow-up would be a nice first PR for someone fwiw

wenkokke commented 2 years ago

I think it makes more sense to discuss this while we’re working on Rust support as rust pattern matching capabilities and syntax is more complex than that of Haskell. And it’s such an integral part of the language that I don’t see much sense adding rust support without pattern matching support.

Wait, could you elaborate how Rust’s patterns are more complex? I don’t think I follow.

(I do agree, though, that they’re an essential part of any language which supports them.)

purpleP commented 2 years ago

I think it makes more sense to discuss this while we’re working on Rust support as rust pattern matching capabilities and syntax is more complex than that of Haskell. And it’s such an integral part of the language that I don’t see much sense adding rust support without pattern matching support.

Wait, could you elaborate how Rust’s patterns are more complex? I don’t think I follow.

(I do agree, though, that they’re an essential part of any language which supports them.)

Unless some extensions were added to GHC or I am missing something Haskell’s pattern matching can only do the opposite of a type constructor, right (aside from primitive types)? It can only match against a type constructors, right?

And in rust they’ve added a few additional ad-hoc features like slice patterns, guard clauses and ability to match on numeric and alphabetical ranges.

wenkokke commented 2 years ago

Ohh, I didn't know about those! On the Haskell sided, boolean guards, pattern guards, pattern synonyms, record patterns, and view patterns complicate things as well.

However, I think it'd make sense to start by designing for just the basic patterns on algebraic data types.

purpleP commented 2 years ago

@pokey I like your proposal.

pokey commented 2 years ago

Ok I've edited my comment above with some new terms after a discussion with @AndreasArvidsson and @phillco. Tl;dr:

See the updated comment for discussion