8
$\begingroup$

Inline assignment is when the assignment operator can return the value of the new-value (right-hand) operand. For example:

if ((homedir = getenv("HOME")) == NULL) {
    // ...
}

I see inline assignment as a hack to make code less redundant. Certainly useful to minimize the number of helper variables that need to be created or evaluating expressions more times than need be. I can also assign multiple items to one value without having to use a variable or repeat the value:

x = y = z = 0;

However, are there downsides to supporting inline assignment? Are there better options for their use cases, such as the aforementioned example?

$\endgroup$
1
  • $\begingroup$ "I see inline assignment as a hack to make code less redundant." - Is this an essential point to the question? (is it necessary to understand the question and to answer it?) It seems to me something that should belong in elaborated form in an answer post. Consider the possibility that you are leading the question in a way that taints answers. Would that be intended? $\endgroup$
    – starball
    May 21, 2023 at 20:29

4 Answers 4

10
$\begingroup$

One downside is that this syntax can't be used in variable declarations, only in assignments. For example, in a language like Java which requires variables to be declared before they are used, the following line will give an error because y isn't declared:

int x = y = 0;

Theoretically there could be a special case for this syntax, so that this statement would declare both x and y as new variables; but this would be surprising since y = 0 is a perfectly valid expression when y already exists, so somebody could write the above expecting to assign to the existing variable y, in which case they would not expect the statement to declare a new variable with the same name, shadowing it.


This is particularly a problem in Javascript, which requires local variables to be declared (as var, let or const) but global variables don't need to be. The following statement in Javascript won't fail at either compile-time or runtime:

var x = y = 0;

But it doesn't do what the programmer really intended: it declares x as a local variable, but assigns to y globally, possibly overwriting an existing global variable of the same name.


It may be worth noting that this isn't a problem in Python, because Python uses separate global or nonlocal declarations to determine whether a given name in this scope is a local variable or not. So

(x := (y := 0))

in Python (using assignment expressions) can't accidentally assign to a nonlocal variable y. The same applies to multiple assignments like x = y = 0, but in Python's syntax this is only allowed as a statement, not an expression.

$\endgroup$
1
  • $\begingroup$ It would certainly be possible to make it also work for declarations: int x = (int y = 0); $\endgroup$
    – xigoi
    Sep 2, 2023 at 19:40
10
$\begingroup$

Another downside is that it leads to code like:

if (a == b) …
…
if (x = y) …

Is the second condition a test with a typo, or an inline assignment and test?
I ran into far too many instances of those during my career.

(Note that things were often coded this way because older compilers would generate more code for separate x=y and if (x==y) … statements.)

In those cases where I did use the second form, I'd write it as:

if (0 != (x=y)) …

The intent is clear and the same machine code will be generated.

$\endgroup$
3
  • 1
    $\begingroup$ Inline assign-and-test is fairly common for one specific case in Objective-C: if ((self = [super init])) prevents the rest of your initializer from running if the superclass initializer failed. $\endgroup$
    – Bbrk24
    May 21, 2023 at 15:22
  • $\begingroup$ The potential typo of if (x = 1) is what leads people to write "yoda conditions", e.g. if (1 == x) $\endgroup$
    – Barmar
    Sep 5, 2023 at 20:11
  • $\begingroup$ How about having a language where x=y does not yield a value, but x:=y; would be an assignment expression that yields the value that was assigned, and x=:y would be an assignment expression that yields the value of the object prior to assignment? $\endgroup$
    – supercat
    Sep 7, 2023 at 20:54
6
$\begingroup$

The main downside of inline assignment is that it creates confusion between = and ==.

There are two workaround I know off:

  • You could special case expressions like x = y = z = 0 when they appear as their own statement. This is what python does.
  • You could just not use = for assignment. Either always use := style assignment like Pascal or use := only for inline assignment like python.
  • While this wouldn't work in the x = y = z = 1 case, a way to embed arbitrary statements inside expressions would also allow assigment. For example, in rust x = {y = {z = 0; z}; y}; x}; For just assigning the same value to many variables it is a bit verbose but this allows more flexibility when for example assigning in a loop condition.
  • For assignment inside loops or conditionals specifically you could have a if let/while let construct that allows you to check a condition and assign to a variable at the same time.
$\endgroup$
3
  • $\begingroup$ I think this might be suffering from a misunderstanding of the question. I've been talking with the asker to make the question more clear. $\endgroup$
    – starball
    May 21, 2023 at 20:01
  • $\begingroup$ @starball I do think the if let and special casing a = b = c are good alternatives to assignment expressions without the obvious downsides, and the other options too but to a lesser degree $\endgroup$
    – mousetail
    May 21, 2023 at 20:04
  • $\begingroup$ How about having = syntax for assignment outside expressions, but some other syntax such as := for assignments within expressions in cases where they would facilitate the tasks programmers need to perform. $\endgroup$
    – supercat
    Sep 7, 2023 at 20:56
-2
$\begingroup$

Disadvantage: Same object ID

In Python, all variables assigned using this method will have the same object ID. This can be undesirable because

x=y=z=[]
x.append("hi")

will add the string “hi” to all lists instead of just list x. TIO Link in case you don’t believe me.

Workaround: using exec()

def massassign(list,val):
 for x in list: # Iterate through the list
  exec(x+"="+val) # Assigns the value to the variable. Value has to be in string form, like "2" to assign the integer 2 or "'hi'" to assign the string 'hi'.

Note that exec() is very dangerous if you allow other users to access your hosted script.

$\endgroup$
8
  • 4
    $\begingroup$ How is this related to having a inline assignment operator in a language? $\endgroup$
    – mousetail
    May 21, 2023 at 13:08
  • $\begingroup$ Make sure you read everything @mousetail $\endgroup$ May 21, 2023 at 13:29
  • 1
    $\begingroup$ Still not related to the question at all $\endgroup$
    – mousetail
    May 21, 2023 at 13:46
  • 1
    $\begingroup$ Note the question is about assignment expressions, multiple assignment is just one example of how it could be used $\endgroup$
    – mousetail
    May 21, 2023 at 13:47
  • 4
    $\begingroup$ Yes, it's totally unrelated. The equivalent, with only assignment statements, is z=[]; y=z; x=y and that shows exactly the criticised behaviour (which may be desired or not, according to the problem domain). $\endgroup$ Jul 7, 2023 at 10:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .