This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Cranium's profile picture

Concatenation using ternary operators

Started by Cranium, 14 May 2015 - 01:44 AM
Cranium #1
Posted 14 May 2015 - 03:44 AM
I'm trying to concatenate some strings I have from one of two different tables, where if one table string doesn't exist, then I would concatenate with the other.

The line I am using is
write("Type: "..alias[list[num].label] or list[num].label)
where alias[list[num].label] may not exist, but if it doesn't I want to use list[num].label instead. Unfortunately, I keep getting an 'attempt to concatenate string and nil' error, where it seems it's ignoring my perfectly reasonable intentions and only going after the first part of the operator.

Can someone help me figure out what I'm doing wrong?
Bomb Bloke #2
Posted 14 May 2015 - 03:48 AM
Seems it's being read as:

("Type: "..alias[list[num].label]) or list[num].label

You should insert your own brackets to make it explicit as to what you're meaning:

"Type: "..(alias[list[num].label] or list[num].label)
Edited on 14 May 2015 - 01:56 AM
Quintuple Agent #3
Posted 14 May 2015 - 03:51 AM
I believe it is trying to concatenate the string first, then check the or statement. It should look like this

write("Type: "..(alias[list[num].label] or list[num].label))

I tried a simple code of

print("Hello ".. nil or "world")

print("Hello ".. (nil or "world"))

print("Hello ".. (nil) or "world")
Only the one that has the whole OR statement in brackets worked
Cranium #4
Posted 14 May 2015 - 03:59 AM
Seems it's being read as:

("Type: "..alias[list[num].label]) or list[num].label

You should insert your own brackets to make it explicit as to what you're meaning:

"Type: "..(alias[list[num].label] or list[num].label)
Fantastic. That worked. So I guess it's just finicky about order of operations. I knew my middle school math teacher made sense sometimes, but I never though it would come in handy when writing programs. Who knew school taught you useful things?
Bomb Bloke #5
Posted 14 May 2015 - 04:15 AM
What's interesting is that the order varies depending on what you're doing - multiple assignments on the one line might be handled differently depending on the specific interpreter you're using.

This wouldn't affect your specific example (where basic order of operations would've always caused it to break), but it does affect stuff like this:

local counter = 0

local function getNum()
	counter = counter + 1
	return counter
end

local var1, var2 = getNum(), getNum()

print(var1 .. " " .. var2)

It'll either print "1 2" or "2 1", depending on the VM. So it pays to avoid this sort of construct even if it seems to work the way you want it to.
flaghacker #6
Posted 14 May 2015 - 08:11 AM
What's interesting is that the order varies depending on what you're doing - multiple assignments on the one line might be handled differently depending on the specific interpreter you're using.

This wouldn't affect your specific example (where basic order of operations would've always caused it to break), but it does affect stuff like this:

local counter = 0

local function getNum()
	counter = counter + 1
	return counter
end

local var1, var2 = getNum(), getNum()

print(var1 .. " " .. var2)

It'll either print "1 2" or "2 1", depending on the VM. So it pays to avoid this sort of construct even if it seems to work the way you want it to.

Could you explain your example? What's so special about that code that it makes diffrent VM's produce diffrent results?
Edited on 14 May 2015 - 07:19 AM
Bomb Bloke #7
Posted 14 May 2015 - 11:49 AM
If the left-most getNum() is resolved first, it'll be 1; if the right-most getNum() is resolved first then that'll be 1. The other will be 2, as "counter" increments with each call.

Even if you know which way around the interpreter you're using will resolve things, that doesn't mean they all will. To be explicit, you might split up the assignments like so:

local var1 = getNum()
local var2 = getNum()

In ComputerCraft, the arguments to the right of the assignment operator are resolved left to right… but the variables to the left of the assignment operator are handled the other way around!

a, a = 1, 2
print(a)  --> 1

This seems to be the way of things under the few other interpreters I've checked, as well. Read more here, if you're interested.
flaghacker #8
Posted 14 May 2015 - 12:27 PM
Thanks for the explenation and the interesting link :)/>. I can't see how this is relevant to the OP though :P/>
Cranium #9
Posted 14 May 2015 - 03:29 PM
It's not, really, but it's certainly interesting behaviour.
flaghacker #10
Posted 14 May 2015 - 05:20 PM
It's not, really, but it's certainly interesting behaviour.

Yea sure, I happy he posted it.