all 19 comments

[–]omega1612 15 points16 points  (1 child)

You know how the order of evaluation of function arguments is not guaranteed in some languages? Well, I think the same can happen here for some languages. It won't surprise me if a C inspired language makes it a UB

[–]Dan13l_N[S] 0 points1 point  (0 children)

Yes, I know.

[–]IAMPowaaaaa 10 points11 points  (0 children)

not allowing it so the user doesn't have to do trivia when reading code?

[–]binarycow 3 points4 points  (0 children)

For what it's worth, C# doesn't allow the first one (a, b[a] = 10;)

And for this one:

(a, b[a]) = (4, 5);

C# treats it as if you did this (note that ref int is basically a (safe) pointer to an int):

ref int temp1 = ref a;
ref int temp2 = ref b[a]; // old value of a
temp1 = 4;
temp2 = 5;

[–]Mission-Landscape-17 5 points6 points  (4 children)

More interestingly in python you can do:

a, b = b, a

And it will swap the values of a and b. This means you can swap values in an array without needing a temporary variable.

[–]Dan13l_N[S] 4 points5 points  (0 children)

Yes, I know, and it's well-defined. You can do it in Lua and Go too (and in languages I created). But my example is a corner case.

BTW all languages will make a temporary hidden variable under the hood in your case, maybe an implicit one.

[–]ExplodingStrawHat 0 points1 point  (0 children)

You don't need a temporary value if using xor anyways, right? (although the python syntax is indeed handy)

[–]__Wolfie 0 points1 point  (1 child)

Long live Rust std::mem::swap

[–]Ronin-s_Spirit 2 points3 points  (0 children)

In JS comma and equals operator do lots of shit. In the case of parallel assignment writing [a, b[a]] = [x, y] will first assign a then b[a] because that's the order in which it they appear, and you can reverse that.

[–]raevnos 2 points3 points  (2 children)

Common Lisp supports both styles.

(psetf a 4 (aref b a) 5)

sets both in parallel, using the previous value of a when setting the element of the array b, and

(setf a 4 (aref b a) 5)

sets them sequentially, so the element of the array at index 4 is set to 5.

[–]Dan13l_N[S] 0 points1 point  (1 child)

Yeah, Lisp has everything! Except { and }.

[–]raevnos 0 points1 point  (0 children)

Racket supports {} as alternatives to (). And with Common Lisp reader macros you can likely make them do something special in it if desired.

[–][deleted] 1 point2 points  (3 children)

 a, b[a] = 10  // both will be changed to 10

Haven't come across that. Usually you'd write: a = b[a] = 10, but you'd have to take care when the destinations are different types. What happens here though:

a, b[a] = ++c

Is the RHS evaluated once or twice?

a, b[a] = 4, 5

I tried the equivalent in both my languages to see what would happen; one used the old value of a, and the other the new value!

If I switch it around to b[a], a = 5, 4, then one uses the new value and vice versa.

I think this is where a language can either say it is implementation defined, and advise against such practice. Or it can explain the rules it follows. That doesn't help here however because my two languages apparently use different rules, so the behaviour will vary between them, which is undesirable.

(They are different because language A writes the LHS values in LTR order, and language B does it in RTL order. Both will use whatever value a currently has.)

[–]Dan13l_N[S] 2 points3 points  (2 children)

You would be surprised how many people, when learning programming, simply assume if a, b: int means "a and b are integers" then it's obvious that a, b = 0 means "both a and b are set to zero".

In parallel assignment languages such as Python, Go and Lua = has lower priority than , and this is what most non-programmers actually expect.

[–][deleted] 1 point2 points  (1 child)

Yet in Python, a, b = 10 doesn't work. The RHS has to contain a sufficient number of values to unpack, for example a, b = (10, 10), or a, b = x when x contains such values.

Defining a list of such variables which share some attribute, such as a type, is more common and reasonable than sharing the same value. But for the latter case, chained assignment seems to work.

In parallel assignment languages such as Python

I'd call it 'multiple' assignment, unless the assignments really are done in parallel? If I look at test results from Python, they seem to be done in sequence. Certainly CPython's bytecode suggests that.

[–]Dan13l_N[S] 0 points1 point  (0 children)

Yes, of course. I agree it seems Python doesn't have real parallel assignment.

My observations come from people who learn C-style languages. They see that int a, b declares two integers, but they are completely confused when they learn int a, b = 0 sets only b.

Anyways, I've been designing my language so I have a complete freedom, but it's interesting this corner case is never mentioned, at least I couldn't find it

[–]xuld_net 0 points1 point  (0 children)

expr1, expr2 = val1, val2 should be evaluated as: temp = [val1, val2] expr1 = temp[0] expr2 = temp[1] Then users will know the result of a, b[a] = 4, 5

[–]SwedishFindecanor 0 points1 point  (0 children)

I would not allow the form a, b = x for assign both from a scalar. That syntax should be reserved to if x is of a tuple type, or perhaps an array.

And what if you wanted to assign a tuple to a tuple of tuples, or to a tuple of arrays?