-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Proposal: Change @
to as
#9829
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
More precedence for precedence: lampepfl/dotty-feature-requests#120 Changing the symbol instead of the precedence feels quite normal. Maybe allow |
TBH I don't like that we are still introducing completely new changes this late in the process. We're already swamped in changes that we cannot keep track of. Independently of that, this seems to be a very cosmetic change that is not justified by anything else than "it does not look nice; let's use something nicer". If we really have to change how binding works in pattern matching, I'd like something deeper. I would like a real analogy with x match
case s & Success(x, in1) => ...
case f & Failure(_, in1) => ...
e match
case (xs & hd :: tl, y) => ... This is very semantic: I want the scrutinee to match both the pattern on the left (which is a capture, so a binding) and ( There would be no restriction on what we can put on the left and on the right. We could actually put a pattern on the left (I have occasionally wanted to match on something that had to satisfy two different patters/extractors). The very concept of a binding would cease to exist. All we would have would be captures. That would actually simplify the language. |
@sjrd Rolling this into conjunction is indeed very elegant. But I believe it is also a lot more obscure for the reader who is not familiar with the idiom. For the cases with |
It's more like: I find it awkward teaching this. Can we avoid that? It's not a matter of nicety but of promoting the right intuitions for students. |
I find @sjrd’s suggestion very elegant. To add to Martin’s introductory post, here is what the proposal would look like in the other situations where we currently use // val someX @ Some(x) = Some(42)
val someX as Some(x) = Some(42)
// for (xs @ hd :: tl <- eventuallyInts) ()
for (xs as hd :: tl <- eventuallyInts) () |
Note that val (_, Captured @ _, NoInits @ _) = newFlags(32, "<captured>", "<noinits>") This makes an uppercase identifier a bound variable. I believe there's no other way to do this, except for writing separate val definitions. |
It's worth noting that both SML and OCaml use There was also the idea of allowing val keys = Set(a as newKey("a"), b as newKey("b"), c as newKey("c")) instead of the verbose: val a = newKey("a")
val b = newKey("b")
val c = newKey("c")
val keys = Set(a, b, c) |
Rust is currently using |
Would as be a soft keyword and hence still usable in type and term names? |
Yes, |
So I'm a fan of the proposed syntax, just not a fan of making more waves so late in the game. Most usage of Dotty right now is cross compiling with Scala 2, so it's not a huge impact, but I feel like the bar should be pretty high for such changes. One immediate problem that this creates, for example, is the fact that "as" is actually a commonly used function name across the Cats ecosystem. I believe it's also quite common in a number of other libraries (with varying meaning). All of those would need to be stuffed into backticks during migration (this is a problem that "then" really doesn't have for some reason), and that's more pain on the ecosystem and more pain on users. (Edit: the soft keyword proposal above resolves this concern) If I could rewind a decade and make the change you're suggesting, I would be all in favor of it. But at this stage, I feel it's a little too much in a process which is already fraught with variables. |
Worth noting that pattern alternation doesn't currently parse as infix:
Scala 2.12 allows an extractor named
|
@djspiewak One possibility would be to try it out now, and if anything major breaks backtrack. The only thing that would break is if some code uses |
Lower case "as" can't be used infix in patterns without quoting (I believe) so I think that case is alright. I'm cool with "try it and see", so long as we watch carefully as we do. 🙂 |
It can be used, actually: case class as(x: Int, y: Int)
val x = as(1, 2) match
case 1 as 2 => ??? But maybe nobody did use it that way. |
does that mean no Scala 2 source can be cross-compiled without resorting to |
but I'm willing to forgo this in future. Edit: I just got the pun from earlier, "a process fraught with variables." |
Regarding &, it's pretty easy to implement in userland, and I have. I might
be misremembering, was it Spray that first used it?
object & {
def unapply[A](a: A) = (a, a)
}
…On Sun, Sep 20, 2020, 6:33 PM som-snytt ***@***.***> wrote:
scala> val as = "(a*)(.*)".r
val as: scala.util.matching.Regex = (a*)(.*)
scala> "aaabbb" match { case as as bs => s"$as .. $bs" }
val res0: String = aaa .. bbb
but I'm willing to forgo this in future.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#9829 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAYAUCX5GGZDTKLCKDP6FLSGZ7LJANCNFSM4RS4MP7Q>
.
|
does that not mean that |
@NthPortal it actually can: scala> object as {
| def unapply[A](a: A) = (a, a)
| }
// defined object as
scala> Some(1) match { case a as Some(x) => (a, x) }
val res2: (Some[Int], Int) = (Some(1),1) Recommending the use of this operator (which would be added to |
As much as I like implementing |
I'm pretty sure named extractors plus value classes allows you to do it in
a way that avoids the boxing
…On Mon, Sep 21, 2020, 4:32 AM Tamer Abdulradi ***@***.***> wrote:
@NthPortal <https://github.com/NthPortal> it actually can:
scala> object as {
| def unapply[A](a: A) = (a, a)
| }// defined object as
scala> Some(1) match { case a as Some(x) => (a, x) }val res2: (Some[Int], Int) = (Some(1),1)
Recommending the use of this operator (which would be added to Predef)
and deprecating @ would be a nice way of simplifying the language.
As much as I like implementing @/as in the userland, I am worried about
the cost of tuple instantiation.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#9829 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAYAUBVQ7LFWLQ4IXWXXGLSG4FSTANCNFSM4RS4MP7Q>
.
|
@LPTK It's interesting that one could define |
TBH, I find the capitalized names as binders a fringe use case, bordering on abuse of the feature. Not as bad as abstract case classes, but still. But anyway, it doesn't matter. There's one thing that val tree: Tree = ???
tree match {
case Apply(sel & Select(_, _)) =>
sel.qual // does not compile: sel is a Tree, not a Select
} and I don't think there is any way to either a) implement that in user-space nor b) correctly specify with a language-defined commutative So I'm afraid we do need the concept of binder as defined in the language. |
@sjrd good point. You can always write
Given a pattern |
I personally don't really like the keyword |
Pattern matching is already prohibitively slow for any code which is sensitive to allocations, so I'm not sure that we need to worry too much about adding a single layer of boxing in this case. I'm worried more about the interaction between this feature and tableswitch, which currently works just fine using @, but would break the optimization if it were not a primitive. |
I like this proposal. From perspective of explaining scala pattern matching to new people, 'as' makes more sense than '@' |
There's already a discussion in #9837 about the order of the operands of |
Actually couldn't we simply have syntax like
by analogy to
? |
The syntax is ambiguous if you have Foo.unapply defined
Edit: Actually scratch that. What I mean saying is ambiguous if `Foo` itself is a defined value you want to match against
Edit 2: To clarify what I meant above:
```
type Foo = Int
val Foo = 42
42 match {
case foo @ Foo => println("foo the value")
case foo: Foo => println("foo the type")
}
```
Cases above would be ambiguous if removed `@` syntax in favor just `:`
…On Mon, Sep 21, 2020 at 4:34 PM Michał Pałka ***@***.***> wrote:
Actually couldn't we simply have syntax like
case foo: Foo(_) => ...
by analogy to
case foo: Foo => ...
?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#9829 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFRBVTWG46OGQYPIR6GCQ3SG5XBJANCNFSM4RS4MP7Q>
.
|
Because of the mixed precedents for order, there is a danger that a beginner might write their patterns as-backward. |
If we can't reuse
The only problem I can see for now would be with patterns like
if we decide to change precedence of bindings in patterns. |
Hum, perhaps, yes. I can't convince myself either that it would indeed work or that it wouldn't. If it works, that would be very nice! |
I find F#'s syntax, where the order of pattern and x match
case Success(x, in1) as s => ...
case Failure(_, in1) as f => ...
e match
case (hd :: tl as xs, y) => ... Why it's better? Because patterns are placed immediately after |
@odersky Big 👍 from me given it's a soft keyword, and the pedagogical benefits of aligning this with |
Fix #9829: Allow `as` in place of `@` for pattern bindings
Can I ask if |
Check #9829 (comment)
|
Uh oh!
There was an error while loading. Please reload this page.
I have a late syntax change proposal: Change
@
as the pattern matching binder toas
.Example:
Why
@
is not a good choice for pattern matching:It is an obscure symbol with a different meaning. I find the two worst operators to use in programming languages are
@
and$
since both have everyday uses that have nothing to do with their role in programming. We have avoided$
so far, let's get rid of@
as well.It comes with the wrong precedence.
@
binds more weakly than every other infix operator, yet being a non-standard symbol it would suggest that it binds more strongly.By contrast,
as
is readable and it comes with the right precedence. It also reinforces learning in relation to givens. In both casesx as
would be an optional label.An objection could be that in patterns,
as
would be followed by a pattern whereas in givens it's followed by a type. But there's precedence for that:|
plays a similar dual role: it connects patterns in patterns and types in types.Migration
For 3.0, allow both
as
and@
. For 3.1. either deprecate@
or disallow it altogether and offer an automatic rewrite.The text was updated successfully, but these errors were encountered: