Skip to content
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

SIP-59 - Multiple assignments #73

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

kyouko-taiga
Copy link

No description provided.

@anatoliykmetyuk anatoliykmetyuk changed the title Multiple assignments SIP-59 - Multiple assignments Jan 19, 2024
@anatoliykmetyuk anatoliykmetyuk changed the title SIP-59 - Multiple assignments Multiple assignments Jan 19, 2024
@anatoliykmetyuk anatoliykmetyuk changed the title Multiple assignments SIP-59 - Multiple assignments Jan 19, 2024

(x, a(0)) = (false, 1337)
(x, a(1)) = f
((x, a(1)), b(2)) = (f, 9000)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "nested tuple only" structure here is a bit odd IMO

We don't really have anywhere else in the Scala language where we have "nested tuples only". Scala has things like:

  • Patterns, which can be nested tuples or extractors
  • Expressions, which can be tuples, or function calls
  • Some places where we have flat lists only, e.g. val a, b, c = Value

I wonder if it's possible to generalize this a bit to accept arbitrary patterns? At least then this will "look like" a pattern, so it's similar to other things in Scala? Or if not, e.g. due to syntactic conflict, we should document it in the Alternatives section

def b = a
var x = false

(x, a(0)) = (false, 1337)
Copy link

@lihaoyi lihaoyi Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the limits of the a(...) syntax?

(x, a("key")) = (false, "value") // Non-integer literals?

val i = 10
(x, a(i)) = (false, 1337) // Integer non-literals?

(x, a(i * 137)) = (false, 1337) // Non-trivial Expressions?

(x, a(1, 2)) = (false, 1337) // Multi-dimensional `update` assignment?

(x, a(foo.bar.qux(1))) = (false, 1337) // Looking up an array by index and using it in the assingment?

From what I understand, all these examples should just work right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposal does not suggest any restriction should apply. If a(x) = rhs is legal scala, then (a(x), b) = (rhs, 2) is also legal no matter what kind of expression is substituted for x.

(x, a(0)) = (false, 1337)
(x, a(1)) = f
((x, a(1)), b(2)) = (f, 9000)
(x) = Tuple1(false)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just prohibit Tuple1 assignments? I feel like there are sufficiently few places where people actually want a Tuple1 that we do not need to support it. We can also add it later if it turns out to be really necessary, so might be good to keep our options open for the initial proposal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Also, when it's "really needed", one can always write ._1 on the right-hand-side instead, with the same evaluation order.

var x = false

(x, a(0)) = (false, 1337)
(x, a(1)) = f
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be perhaps more simple if it were only syntactically "tuple literal" expression on the left and right, then you can check for arity match in the parser, and perform rewrites in desugar before typechecking. Otherwise here you must introduce pattern match extraction on f which is more complex.

Copy link

@lihaoyi lihaoyi Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think allowing tuple-typed values on the RHS is not truly-necessary, but it's definitely a nice-to-have, so even if it adds a bit more implementation complexity I think we should try to do it.

Having to manually unpack tuples to say (x, a(1)) = (f._1, f._2) just sounds awfully verbose and counter-intuitive, especially since (f._1, f._2) is meant to be the same as f in most other contexts

@lihaoyi
Copy link

lihaoyi commented Jan 19, 2024

I like this proposal in general. I've hit all the pain points in my own experience. Scala has always been a hybrid language, and the way the immutable multiple-assignment with val does not have a mutable multiple-assignment equivalent has always been a bit of a wart.

There are some subtleties around the implementation, especially around evaluation order, but from a UX perspective I think we should definitely have this.

@kyouko-taiga
Copy link
Author

Proof of concept implementation is in progress (see here).

@sjrd
Copy link
Member

sjrd commented Feb 16, 2024

We discussed this SIP during today's meeting. Although we did not vote on it yet, there is broad consensus that we want to accept it.

We have two pieces of feedback regarding the somewhat open questions. Overall, the committee would be in favor of:

  • Only allow one level, flat tuple on the left
  • Allow an arbitrary expression of the right tuple type on the right

Comment on lines +269 to +270
The compiler is allowed to ignore this procedure and generate different code for optimization purposes as long as it can guarantee that such a change is not observable.
For example, given two local variables `x` and `y`, their assignments in `(x, y) = (1, 2)` can be reordered or even performed in parallel.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here the committee would prefer stronger wording: that there be a guarantee that no closure is actually allocated in the implementation. The closures are only mentioned to make the behavior clear.

@sjrd
Copy link
Member

sjrd commented Mar 15, 2024

The SIP committee voted today to accept this SIP at the Design stage, modulo the comments from last meeting (just above).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants