Assignment as an Operator Behavior

I’ve been looking at different operators and ran into one that has a particularly unusual behavior. I am not sure if this is a special case, or if it is a hint that there is something about operator behavior more generally I do not understand. Would love people’s thoughts on this!

Here’s the code with comments regarding what each line it outputs vs what I expect.

⍝ Outputs 5 : I expected 5
⎕ ← a ← 5

⍝ Outputs 1 : I expected 6
⎕ ← (a +← 1) 

⍝ Outputs 6 : I expected 6
a

It seems like when is used as an operator it does assignment immediately but delays the increment part until the next line? Meaning you can’t use assignment as an operator to modify a variable and reuse that variable on the same line as it’s value won’t have been updated yet, even if the operator is in parenthesis for the highest precedence.

Rather confusingly, can be a function, or an operator. Your first example above uses it as a function.

As an operator, it returns RHS before modification. It’s like ++ used as a prefix in C++.

It seems like it returning the RHS before modification is a different behavior that other operators, isn’t it?

Normally I think operators combine and then act as a function following normal precedence from there. If a computation is done first it can be immediately used on the same line. For example

For example (a ← +/ 5 6) + 1 outputs 12 - we have the final value immediately and use it immediately.

However (a +← 1)+1 behaves differently with this outputting 2 regardless of what a was because the operator returns the RHS as you mentioned. So we do not have the final value immediately and cannot use it immediately. It seems like it acts like a the left arrow function in line, but the actual arithmetic happens much later.

I can’t think of another operator that behaves this way where the final result isn’t available in the current line of execution.

As possibly a better example would be to compare how (a ∘+ 1) + 1 behaves compared to (a +← 1) + 1.

a ∘+ 1 calculates immediately but doesn’t do any assignment. a +← 1 does assignment of 1 immediately and delays the calculation of adding 1 until after the entire line is calculated.

If we add assignment in (a←a ∘+ 1) + 1 this still outputs a different value than (a +← 1) + 1 if a does not equal 1 before these statements.

You’re still using the function above, not the operator. To get the operator, reverse the order: +←.

IIUC, the operator creates a function that returns its RHS, whilst assigning the result of the function to the LHS.

@abrudz FYI the Dyalog docs linked from the operator page, with the link text “modified assignment”, don’t seem to actually mention modified assignment. I don’t know if it’s documented elsewhere in the Dyalog help – I didn’t manage to find it.

Ah I should have copied from APL instead of retyping in the thread! Yes, fixed all examples of ←+ should have been +← in the 2nd/3rd post above. (1st post no changes needed)

a +← 5 is the first scenario I ran into where the return value and assignment do not match. What threw me off is I assumed that in most cases the assignment and the return of value happened at the same time. I believe the value is returned in the line of code using right to left precedence, but all assignment happens after the entire line of code is executed.

In most cases I think this difference in timing isn’t visible because assignment and return value is the same. For example a ← 5+5 seems normal because returns 10 and also assigns the value of 10. I assumed that it returned 10 and assigned 10 to a at the same time.

However, I think the return of 10 happens at the time the function is called, but the actual assignment of 10 probably doesn’t actually happen until after the full line is executed. I had assumed that both happened at the same time, but I think the +← operator is showing otherwise.

I wonder how we can define operators or functions that have different assignment and return values.

It’s true that left arrow as a function and as operator do their assignment at different times, as this shows:
image

1 Like

Thanks for your help! Leaving this example as it was helpful to me for understanding this also, in case it helps others also.

Screen Shot 2022-07-15 at 8.01.13 PM

Thanks. Logged as issue 19946 (stating that here so I can refer back to it).

1 Like

It isn’t that assignment is delayed. There’s just one simple rule to remember for the result of :
The result of is whatever was given on its right. Always. Without exception.

However, the assignment is immediate. Basically, you can see a f←y as shorthand for y⊣a←a f y

Thanks! Maybe a better way for me to think about it in that case would be assignment happens immediately, but the modification portion of +←2 (incrementing 2 to the previous value) doesn’t happen until later.

Maybe, but note that with a←5 the expression a⊣a+←1 does return 6.

Good to know! I definitely was misunderstanding the internals a bit. With a←5, a⊣⎕←a+←1 gives me 1 and then 6. I understand the behavior enough to code with, and the left tack gives me the option to use either of the values :slight_smile:

Thank you for taking the time to help out here :slight_smile: