Please explain this assignment stmt

I saw this and don’t really understand what it is doing.  Would someone please explain. Maybe split it up into easier to understand stmts.  

variable = v == "" and nil or v

I have used   x = y or 12  before meaning if y is null then use 12 instead as the default.  

L  

Stacking multiple lines of code into one line should be banned!   yes we all know you are clever, stop showing off :)  

It is the same as a conditional operator in C: https://fresh2refresh.com/c-programming/c-operators-expressions/c-conditional-operators/
 
The syntax of the statement for Lua is:
 
variable = (CONDITION) and TRUE_VALUE or FALSE_VALUE
 
In other words,
 
If CONDITION evaluates to true , assign the TRUE_VALUE to variable, otherwise assign FALSE_VALUE
 
 
Try this to see how it works:

local function ageMessages( age ) local msg1 = (age \>= 18) and "You are an adult" or "You are a minor" local msg2 = (age \>= 21) and "You can buy alcohol" or "You cannot buy alcohol" return msg1, msg2 end for i = 16, 22 do local msg1, msg2 = ageMessages( i ) print( "Age: ", i, msg1 .. "; " .. msg2 ) end

Result:

4:03:58.806 Age: 16 You are a minor; You cannot buy alcohol 14:03:58.806 Age: 17 You are a minor; You cannot buy alcohol 14:03:58.806 Age: 18 You are an adult; You cannot buy alcohol 14:03:58.806 Age: 19 You are an adult; You cannot buy alcohol 14:03:58.806 Age: 20 You are an adult; You cannot buy alcohol 14:03:58.806 Age: 21 You are an adult; You can buy alcohol 14:03:58.806 Age: 22 You are an adult; You can buy alcohol

Irony: In the the USA you are considered an adult, can join military and possibly die for your country 3 years before you can drink.  (I’m ex-military and I though it was ironic then as I do now.)

Laura,  

I don’t agree with your banning statement (smiley or no). 

Used with some caution, this is an excellent time saver, line saver, and frankly makes it possible to do things you simply couldn’t easily do with easily legible if-then-else style statements.

It is a powerful construct you should definitely learn to use.

However, if you pulled this line from someone’s code, then I agree they need to be more clear:

variable = v == "" and nil or v

A safer and clearer construction of that assignment would be:

variable = (v == "") and nil or v

I believe if there is any possibility that there will be order-of-precedence confusion, one should enforce it with brackets.  This is also true for the TRUE_VALUE and FALSE_VALUE elements if they are complex.

Oh, there is another thing you should be wary of:
 
If you do this it will fail to operate as expected:

variable = (CONDITION) and false or true

This will always assign ‘true’ to variable. 
 
This is obvious once you’re familiar with the language and construct, but I frequently see this mistake made by new users.
 
You can verify this for yourself with this code:

print( 1, (true) and false or true ) print( 2, (false) and false or true )

Prints:

14:14:52.306 1 true 14:14:52.306 2 true

I see both sides here… I agree with laura from a readability perspective and rg from a “why use many lines when one will do” perspective.

A more readable version of

local variable = v == "" and nil or v 

is

local variable if v == "" then variable = nil else variable = v end

or

local variable if v == "" then v = nil end variable = v 

makes no difference to the compiled code… just more readable to most people.

Personally I find the C implementation easier to read than the lua one.

@laurasweet8888 - this is a very common Lua idiom, though granted that the specific use of it you cite is weird/obscure and  I doubt it even does what the author intended!  (it will NOT assign nil to “variable” when v=="" as it seems to imply was its intent, see @spheregamestudios rewording of it for a version that would work properly if that’s it’s intended function).

this tends to happen only if you believe that it is truly equivalent to C’s ternary operator - which it isn’t.  if you understand what it _ is _, then it operates exactly as expected.

it’s just a boolean expression, so if you replace “CONDITION” with either true/false and evaluate the expansions (“false and false or true”, “true and false or true”), keeping in mind order of operations (and before or) you’ll find they both evaluate true.

then for @laurasweet8888’s specific example, consider that nil evaluates as false in a boolean expression and you’ll see that the OP code probably doesn’t do what it thinks it does.  so not only is it obscure, it’s probably broken.  (where “probably” means “almost certainly” - I can’t see anything useful that code actually accomplishes beyond “variable = v”)

C’s ternary operator would evaluate only  “CONDITION” as the conditional boolean expression.  (one of the other two expressions would also be evaluated, but as part of the assignment, not as part of the conditional)

@laurasweet8888 - fwiw, IFF our guess as to what the original code was intended to do is correct (assign v to variable, unless v is the blank string, in which case assign nil to variable) then this would have been the proper formulation using Lua’s ternary-style idiom:

variable = v~="" and v or nil

it looks similar but is critically different!

Thanks for the explanations.  I like my code to be clear and readable.  This is what drew me to Lua in the first place.  If I wanted totally unreadable code I would have chosen perl. 

This seems way clearer and still only takes up one line.  So it seems like the logical way to go.  

local variable
if v == “” then variable = nil else variable = v end

This is the code snippet I was trying to understand.  Of course, I knew what it was doing.  It just bugged me that I didn’t exactly know how it was doing it.  

local function inherit(image, properties) for k,v in pairs(properties) do image[k] = v == "" and nil or v end return image end

rewrite it - you might want to rewrite for style, and no problem there, but  need to rewrite because it doesn’t do what it seems to.

I just had 2 thoughts.  I know it happens from time to time. 

1.  That loop can be used to combine tables but also to implement simple OOP inheritance. 

2.  Since you delete variables in Lua by setting them to nil, it seems that loop is actually deleting a bunch of blank variables.  

If that was the intent then great .  Can you even initialize a Lua variable to nil?  That doesn’t seem like a thing you can actually do.  

You  can set a variable to nil. 

It simply clears the variable.

If that variable was referring to a previously deleted display object, or if it was referring to a table and the object/table has no other references, it can now be garbage collected (different from deletion).

local obj = display.newCircle( 10, 10, 10 ) display.remove( obj ) -- deleted, but remaining stub table can't yet be garbage collected obj = nil -- now garbage collection can free memory associated with stub of obj

local junk = { } junk[1] = { a, b, c } junk[2] = " junk[1] = nil -- Table that was at 1 can now be garbage collected. junk[2] = nil -- String at 2 can now be garbage collected. -- Note: Table junk has no entries, but is still valid. junk = nil -- Now the table can be garbage collected -- Tip,if we skipped prior nil assignments, the table at entry 1 would be -- garbage collected at this point.

@laurasweet8888

  1. yep, what you have here is a “shallow prototype” type of OOP.  (ie, “shallow” versus “deep”, fe if one of the things inherited is itself a table, then the “image” would just get a reference to the same table, not an entire fresh copy of the table - that would be a “deep” copy).

  fwiw, you could expand upon it for OOP use by taking variable arguments (instead of just the single “properties”) and inheriting from multiple sources in order, fe if you wish to set up a good environment for implementing composition-based OOP (fe dog=inherit(animal,canine,tamed,candotricks).

  or you could just use 30log

  1. yes, except that it won’t actually work as written.  reread my prior comments, then work it through manually - its ternary formulation is flawed.  it might as well just read “image[k] = v” (because the “and nil” portion of the expression will NEVER evaluate true, so it’ll ALWAYS return “or v”)

It is the same as a conditional operator in C: https://fresh2refresh.com/c-programming/c-operators-expressions/c-conditional-operators/
 
The syntax of the statement for Lua is:
 
variable = (CONDITION) and TRUE_VALUE or FALSE_VALUE
 
In other words,
 
If CONDITION evaluates to true , assign the TRUE_VALUE to variable, otherwise assign FALSE_VALUE
 
 
Try this to see how it works:

local function ageMessages( age ) local msg1 = (age \>= 18) and "You are an adult" or "You are a minor" local msg2 = (age \>= 21) and "You can buy alcohol" or "You cannot buy alcohol" return msg1, msg2 end for i = 16, 22 do local msg1, msg2 = ageMessages( i ) print( "Age: ", i, msg1 .. "; " .. msg2 ) end

Result:

4:03:58.806 Age: 16 You are a minor; You cannot buy alcohol 14:03:58.806 Age: 17 You are a minor; You cannot buy alcohol 14:03:58.806 Age: 18 You are an adult; You cannot buy alcohol 14:03:58.806 Age: 19 You are an adult; You cannot buy alcohol 14:03:58.806 Age: 20 You are an adult; You cannot buy alcohol 14:03:58.806 Age: 21 You are an adult; You can buy alcohol 14:03:58.806 Age: 22 You are an adult; You can buy alcohol

Irony: In the the USA you are considered an adult, can join military and possibly die for your country 3 years before you can drink.  (I’m ex-military and I though it was ironic then as I do now.)

Laura,  

I don’t agree with your banning statement (smiley or no). 

Used with some caution, this is an excellent time saver, line saver, and frankly makes it possible to do things you simply couldn’t easily do with easily legible if-then-else style statements.

It is a powerful construct you should definitely learn to use.

However, if you pulled this line from someone’s code, then I agree they need to be more clear:

variable = v == "" and nil or v

A safer and clearer construction of that assignment would be:

variable = (v == "") and nil or v

I believe if there is any possibility that there will be order-of-precedence confusion, one should enforce it with brackets.  This is also true for the TRUE_VALUE and FALSE_VALUE elements if they are complex.

Oh, there is another thing you should be wary of:
 
If you do this it will fail to operate as expected:

variable = (CONDITION) and false or true

This will always assign ‘true’ to variable. 
 
This is obvious once you’re familiar with the language and construct, but I frequently see this mistake made by new users.
 
You can verify this for yourself with this code:

print( 1, (true) and false or true ) print( 2, (false) and false or true )

Prints:

14:14:52.306 1 true 14:14:52.306 2 true

I see both sides here… I agree with laura from a readability perspective and rg from a “why use many lines when one will do” perspective.

A more readable version of

local variable = v == "" and nil or v 

is

local variable if v == "" then variable = nil else variable = v end

or

local variable if v == "" then v = nil end variable = v 

makes no difference to the compiled code… just more readable to most people.

Personally I find the C implementation easier to read than the lua one.

@laurasweet8888 - this is a very common Lua idiom, though granted that the specific use of it you cite is weird/obscure and  I doubt it even does what the author intended!  (it will NOT assign nil to “variable” when v=="" as it seems to imply was its intent, see @spheregamestudios rewording of it for a version that would work properly if that’s it’s intended function).

this tends to happen only if you believe that it is truly equivalent to C’s ternary operator - which it isn’t.  if you understand what it _ is _, then it operates exactly as expected.

it’s just a boolean expression, so if you replace “CONDITION” with either true/false and evaluate the expansions (“false and false or true”, “true and false or true”), keeping in mind order of operations (and before or) you’ll find they both evaluate true.

then for @laurasweet8888’s specific example, consider that nil evaluates as false in a boolean expression and you’ll see that the OP code probably doesn’t do what it thinks it does.  so not only is it obscure, it’s probably broken.  (where “probably” means “almost certainly” - I can’t see anything useful that code actually accomplishes beyond “variable = v”)

C’s ternary operator would evaluate only  “CONDITION” as the conditional boolean expression.  (one of the other two expressions would also be evaluated, but as part of the assignment, not as part of the conditional)

@laurasweet8888 - fwiw, IFF our guess as to what the original code was intended to do is correct (assign v to variable, unless v is the blank string, in which case assign nil to variable) then this would have been the proper formulation using Lua’s ternary-style idiom:

variable = v~="" and v or nil

it looks similar but is critically different!

Thanks for the explanations.  I like my code to be clear and readable.  This is what drew me to Lua in the first place.  If I wanted totally unreadable code I would have chosen perl. 

This seems way clearer and still only takes up one line.  So it seems like the logical way to go.  

local variable
if v == “” then variable = nil else variable = v end

This is the code snippet I was trying to understand.  Of course, I knew what it was doing.  It just bugged me that I didn’t exactly know how it was doing it.  

local function inherit(image, properties) for k,v in pairs(properties) do image[k] = v == "" and nil or v end return image end

rewrite it - you might want to rewrite for style, and no problem there, but  need to rewrite because it doesn’t do what it seems to.