<cfif len(trim(sMyVar)) neq 0>
or
<cfif qry.recordCount neq 0>
or
<cfif arrayLen(structKeyArray(sct)) neq 0>
or
<cfif arrayLen(arr) neq 0>So I came up with a function that I wrote the other day which does these checks for me and I can pass anything I like to it. The function is called isEmpty(any) and takes any kind of variable you pass to it. Then instead of the above I can write:
<cfif !isEmpty(sMyVar)>
or
<cfif !isEmpty(qry)>
or
<cfif !isEmpty(sct)>
or
<cfif !isEmpty(arr)>
Or of course the isEmpty() without the ! in front of it. here's the function and the corresponding test code:
<cfscript>
boolean function isEmpty(required any oObj) {
if (isSimpleValue(oObj)) {
if (isDate(oObj)) {
return true;
} else if (isNumeric(oObj)) {
return oObj eq 0;
} else if (isBoolean(oObj)) {
return !oObj;
} else {
return len(trim(oObj)) eq 0;
}
} else {
if (isArray(oObj)) {
return arrayLen(oObj) eq 0;
} else if (isStruct(oObj)) {
return arrayLen(structKeyArray(oObj)) eq 0;
} else if (isQuery(oObj)) {
return oObj.recordCount eq 0;
}
}
}
return false;
</cfscript>
testIsEmpty.cfm:
<cfinclude template="isEmpty.cfm">
<cfset aTest = [0,
1,
-1,
"",
" ",
"susi",
true,
false,
[],
[1],
now(),
{},
{christine:""},
query("susi":[1]),
query("susi":[])
]>
<cfloop array="#aTest#" index="element">
<cfdump eval=isEmpty(element) label="#serialize(element)#">
</cfloop>
If you want to have the function available for your complete Railo server, just copy it into:
{theDirectoryWhereTheRailoJARFileIsLocated}/railo-server/context/library/function
and if you like to have it in your local context only, it should go into:
WEB-INF/railo/context/library/function
Don’t forget to restart your railo server for it to work. I would appreciate feedback to it. And I suppose Railo 4.1 will have the function built in so that it runs way faster.
9 responses so far ↓
1 Russ // Aug 18, 2012 at 9:22 AM
Numeric, Boolean, and Date types cannot be "empty" conceptually, so you shouldn't attempt to handle them. Throw an error instead.
A string that has a space in it isn't really "empty" either. It has a length of 1.
I think what you've done can certainly be good and useful, however you may wish to rethink your function name. The "empty" concept really only applies well to collections.
Maybe you could break it up into isEmpty for collections, isBlank for strings, and isFalsy for numeric, boolean, and possibly date types?
Remember that someone else will eventually have to work on your code, so try to be reasonably accurate and explicit with your names.
2 Gert // Aug 18, 2012 at 10:44 PM
For the rest I am open...
Gert
3 Russ // Aug 18, 2012 at 11:50 PM
gameNotStartedYet = isEmpty(golfScore);
makePlans = !isEmpty(futureLandingDate);
endOfText = isEmpty(nextCharacter);
And what about other types of non-simple objects, such as xml objects, or other types that CF introduces in the future? I suggest throwing an error for types that you did not plan for. Do you really want to be responsible for this:
launchAllTheNukes = !isEmpty(someTypeYouDidntConsider);
?
Another problem with your code is that CF automagically converts lots of strings into booleans. So isBoolean() will return true for "TRUE", "FALSE", "YES", "NO", "1", "0", "100", "1.1"... So isEmpty("false") returns true, even though I intended to see if the string "false" was to be considered empty (having a trimmed length of 0).
(Also, it looks as though your last "return false" is outside of the function? Probably a cut/past accident?)
If you want to ensure that this function acts as you expect it to, I highly recommend writing some MXUnit unit tests for all the various cases (both positive and negative).
4 Igal // Aug 20, 2012 at 1:38 AM
as for Booleans and Strings -- CFML has always been casting types implicitly, and since the isBoolean() test comes before the String length I think it should be fine.
one thing to remember about writing custom BIFs is that the filename and the function name must be consistent. I'm not sure if that is documented anywhere, so in this case the isEmpty function must be in a isEmpty.cfm file (not case sensitive, of course).
5 James Moberg // Aug 20, 2012 at 5:14 PM
http://www.cflib.org/udf/isEmpty
Also, have you considering using YesNoFormat() for "false"? (Ig guess it's "trueFalseFormat()" for Railo.) What if "false" is a string response to a fill-in-the-blank question or a radio dialog box option. Extra server-side logic would be needed to ensure that these responses are identified as "empty" versus "filled in and negative."
6 Dawesi // Sep 10, 2012 at 1:40 PM
7 Ronan // Nov 8, 2012 at 12:42 PM
This follow the same concept from python where everything is an object.
You have to just:
if myVar:
doThis()
python knows that "" for string is empty/false, 0 for number is empty/false, an array with no objects is empty/false.
It's much more intuitive.
8 Michael Offner // Dec 20, 2012 at 5:13 PM
9 Will B. // Mar 19, 2013 at 7:52 PM
Had to roll back the batch.
- WB
Leave a Comment