It appears that the elvis operator can guard again...
# cfml-general
d
It appears that the elvis operator can guard against many non-existent items (struct keys, array elements, query columns), but not against non-existent query ROWS. Doesn't throw an error, just doesn't use the requested "default". Has anyone run into any other similar limitations?
a
Am trying to guess what your example code might be that demonstrates what you're doing, but try as I might I can't. Have also tried telepathy, but I think you might be out of range. I guess yer just gonna need to stoop to showing us some code. I hate when that happens, I know.
🙂 1
d
Copy code
<cfscript>
	q = queryNew("name", "VARCHAR", []);
	q.addRow({name:"Jack"});
	x = q.name ?: "q.name doesn't exist";
	readout(x);
	x = q.lastname ?: "q.lastname doesn't exist";
	readout(x);
	x = q.name[1] ?: "q.name[1] doesn't exist";
	readout(x);
	x = q.name[2] ?: "q.name[2] doesn't exist";
	readout(x);
	
	function readout(required string t)
	{
		writeOutput("result: " & t & "<br>");
	}
</cfscript>
RESULT: result: Jack result: q.lastname doesn't exist result: Jack result: Instead of "q.name[2] doesn't exist", the last result is just empty string. ...and excuse the tacky tacky quick test...
a
Yeah. Just on CF. @Mark Takata (Adobe) can you get someone to explain this pls? https://trycf.com/gist/fbdcae0bdb1f1e05b33fb689fbead981/acf2023?theme=monokai
m
And here I thought Elvis had left the building. 😛 Elvis is not predictable in ACF. @ben gives a pretty good overview here: https://www.bennadel.com/blog/4231-fundamental-differences-in-elvis-operator-between-adobe-coldfusion-and-lucee-cfml.htm I have a ticket in to the team to create a true null coalscing operator (which would align with Lucee's... as well as basically all other languages). CHANGING elvis would break too much code, but we are considering possibly ?:: or something like that which would have the expected functionality. Call it alien Elvis. Alvis? On the bright side, not passing along the last name keeps the PII safe. You're welcome Dave! (heads up @Charvi @Satyam Mishra @Ashudeep Sharma regarding our recent discussions on Elvis issues, here's a real-world example of it not working as you'd expect).
👀 1
a
If you do do a proper null-coalescing operator, there is precedent for
??
. That aside, not sure you're quite following the use case I was raising, which was nothing about the
?:
operator 😉 The issue is that in a one-row query, checks of elements in row 2 (and subsequent) are
""
, not
null
. That is - objectively, I think - wrong.
❤️ 1
(Dave was seeing a symptom of the issue, not the actual issue)
d
Thanks for following up on this folks, I got pulled off onto a thing. Luckily, I was just trying to make sure I understood how this works, not fixing a mission critical zortout. Fun!
a
> got pulled off /me sniggers like a school boy
m
oh oh oh damn it Dave I was distracted lol
Is it "" or is it does not exist?
Which... ugh, ok I gotta go check my Booleans again. Between CFML and JS Booleans are gonna be the death of me. 💀
OK apologies for misunderstanding. This does seem to be acting oddly. I've sent an email internally to some folks to pop the hood on it and see what's going on. But feels a hell of a lot like a bug.
Dave can you double check for me that null support is turned on?
d
No, null support is NOT turned on, were not ready to deal with that, and don't have a pressing need for it, so far. Did I miss where that's needed for elvis to do his thing? That's not mentioned on the Elvis operator docs page. Also, it's not clear to me that null support is logically required for it to work. A struct key or array element or query column can exist or not without null support, and in fact elvis works in those cases in my explrations.
m
Let me do some testing
d
Not to be a PITA, but the question isn't only how does it work, but what's the spec? How is it SUPPOSED to work? Does that line up with the docs? With observed behavior?
m
What’s the spec for what? Elvis? Query rows? The particular intersection of both in this case?
d
Elvis, in various contexts, whichever ones are supported.
❤️ 1
m
That’s fair, our docs here are kind of weak. Let me see if we can shore them up. But also I DO think you stumbled on a bug as well and I’d like that fixed
👍 1
d
Thanks for poking this, I appreciate it.
a
To be clear: this is not an issue with
?:
. It's an issue with queries misreporting on non-existent rows. As for
?:
expectations... It's the standard short-circuit
? :
(ie ternary operator), with the exception that it treats
null
as falsy (which it usually isn't, in CFML). So CFML's implementation is not quite the usual
? :
short -circuit, nor is it a null-coalescing operator (as
false
is a fail).
I think it was me who first requested this, but I requested a clear null-coalescing operator as
??
(which I'd seen in C#). True to form, rather than listening to me (😜), Adobe implemented something that was neither fish nor fowl.
d
For any still playing along, I've come around to Adam's thinking, that the problem isn't with Elvis, it's with how CF handles references to query rows that don't exist. Row -1 gives the value in row 1, bogus IMO. Row 0 and rows past the number of rows in the query apparently return empty string, also bogus IMO. Note that Elvis protection isn't needed, a direct reference gives the same result as Elvis. All those out of range row numbers should throw an error when referenced directly, and Elvis should return the "default" value. So again, the problem isn't Elvis, it's query behavior. TEST CODE
Copy code
writeOutput("<h3>query rows</h3>");
	q = queryNew("name", "VARCHAR", []);
	q.addRow({name:"Jack"});
	for (n in [-1,0,1,2])
	{
		x = q.name[n] ?: "q.name[#n#] doesn't exist";
		readout("n=#n#: #x#");
		x = q.name[n]; // direct reference gives the same result as elvis
		readout("n=#n#: #x#");
	}
	
	function readout(required string t)
	{
		writeOutput("result: " & t & "<br>");
	}
RESULT
Copy code
result: n=-1: Jack
result: n=-1: Jack
result: n=0:
result: n=0:
result: n=1: Jack
result: n=1: Jack
result: n=2:
result: n=2:
1
1