Coldfusion 9 finally has a ternary operator. It’s certainly a lot prettier to use than an IIF(), and you won’t have to deal with those odd occasions where you need to use DE() to get things to work. Here’s an example of how it works in CF9 and the equivalent using an IIF() and a standard “if” (keep in mind that the loops are to demonstrate performance only – they are otherwise quite out-of-place):
<cfparam name="URL.name"> <cfparam name="URL.isLight"> <cfset startTernary = GetTickCount()> <cfloop from="1" to="10000" index="i"> <cfset beerName = !URL.isLight? URL.name & " is a good beer" : "No light beers in this list!"> </cfloop> <cfset endTernary = GetTickCount()> <cfset startIIF = GetTickCount()> <cfloop from="1" to="10000" index="i"> <cfset beerName = IIF(!URL.isLight, "'#URL.name# is a good beer'", "'No light beers in this list!'")> </cfloop> <cfset endIIF = GetTickCount()> <cfset startIf = GetTickCount()> <cfloop from="1" to="10000" index="i"> <cfif URL.isLight> <cfset beerName = "No light beers in this list!"> <cfelse> <cfset beerName = "#URL.name# is a good beer"> </cfif> </cfloop> <cfset endIf = GetTickCount()> <cfoutput> Ternary: #endTernary - startTernary#ms<br /> IIF: #endIIF - startIIF#ms<br /> If: #endIf - startIf#ms<br /> </cfoutput>
Even over 10,000 iterations, the ternary option is head-to-head with a standard if statement, and only slightly faster than an IIF:
Ternary: 62ms
IIF: 77ms
If: 62ms
I’ve always heard that IIFs were slow, but I’ve always found them so handy that I overlooked whatever the performance consequences might be. While noticeable in these tests, it’s not something that would affect most projects at all. These results are also backed up in this post by Ben Nadel.
I won’t be using CF9 in a production setting in the immediate future, so until then it’ll still be IIFs for me. Still, some of these new language improvements and features are definitely worth looking into (even if they should have been added long ago!).
Dear Hadyn,
Thanks so much for recently donating your car to public broadcasting through the Car Talk vehicle donation program. Your thoughtfulness resulted in a net gift of $35.00 to WITF.
Excellent! Almost enough for a case of good beer… but not anywhere near what the sticker suggests:
Last Saturday, Alison and I headed to see the “abandoned” portion of the PA turnpike, which is now an 8.5 mile trail. There’s all sorts of video and photos online about it, and it surprised me that I hadn’t even known about it prior to stumbling upon PikeToBike.org while looking up some Appalachian Trail info. Perhaps the biggest reason it’s worth going to see is that this section of the turnpike has been abandoned since 1968 and contains both the longest (and shortest) tunnels on the PA turnpike. The whole stretch has kind of a “Centralia, Highway 61″ feel to it because of the cracked roadway, illegal dumping and ample graffitti, but it is nonetheless quite a cool place to visit.
PikeToBike has a lot of information about the trail. It’s not officially open, but is apparently well traveled. We didn’t encounter anyone the entire time we were there. The Sidling Hill tunnel is supposedly 1.3 miles long (I didn’t measure) and… far darker than I expected. The damp tunnels eat light! If darkness weren’t pressing in from outside, too, I’d have liked to explore the ends of the tunnels a bit more. There are some huge fans sitting on top of the entrance of the Sidling Hill tunnel that I’ll have to explore next time. There’s also an air space in the upper part of the tunnel that can be accessed, which would be pretty cool to get into had I been armed with a more powerful flashlight. It was kind of an eery feeling just walking/riding through this tunnel with such a limited amount of light. For some reason I expected to be crashing into abandoned vehicles, old mattresses and the homeless, but both tunnels are barren throughout. However, the effects of vandalism and time are apparant in the entire length of the tunnels and particularly on the tunnel entrances.
PikeToBike lists some of the projects that would be worthwhile on the property; including paving one of the four lanes (in order to make it accessible via road bike) and adding some minimal lighting the the tunnels. This is on top of tunnel maintenance and repair, which is also pretty badly needed. The roadway is pretty rough but is fine for mountain biking. If you’re going through the tunnels, bring a real flashlight!
Go check it out for yourself!
I’ve been eying up the Tweet-A-Watt project for a few weeks now. I think the idea is pretty cool, taking an off-the-shelf power monitoring device (a Kill-A-Watt P3) and tying it to a wireless transmitter in order to get the data from the device to a PC. The tweeting part of the project doesn’t really interest me, but storing power usage data in a database would let me see some long term trends in electricity usage. I might even be able to quell the feeling I have that the “Reduce exterior moisture / Save energy” switch inside of my refrigerator doesn’t do anything.
What I tackled this past weekend was the construction of the wireless reciever (which plugs into my PC via a USB cable) and the transmitter that gets hooked up to the Kill-A-Watt. The entire parts list and assembly instructions are available from ladyada.net. I opted to get the kit out of simplicity. It’s a little pricey, but includes everything you need for the project.
The instructions are pretty good. Provided you are alright with a soldering iron, you can manage just fine – at least up until attaching the power and data wires to four individual pins on the tiny chip found on newer Kill-A-Watts. That part is a little trying. A helping-hands type device is a must have for a project like this and I know that it made things much easier for me. So did a new, super-tiny tip for my soldering iron.
I put the whole thing together according to the instructions and plugged it in. And… nothing happened! I got no display on the LCD and the XBee activity light didn’t blink. The super capacitor takes a while to charge up, but no matter how long I waited, I got no info out of it except for the fact that it would make the standard beeps when the buttons on the front of the unit were pressed. I took it back apart to double check the connections to the tiny chip underneath the LCD display and they seemed fine. I couldn’t see any possible short circuits, but I did read on the forums that it would be important to cut a pathway halfway through the foam on the underside of the display to let the wires out. I also filed a notch in the side of the PCB so that the wires would not be pinched. The LCD has to sit flat in the right location for it to work at all. I double checked the transmitting XBee and discovered that it was not working. I figured I must have fried it as X-CTU couldn’t even communicate with it when plugged into the USB cable. There are instructions about how to revive an XBee that has been put into sleep mode on the forums at ladyada.net. I had to perform the process a few times and it eventually started working again. Upon reassembly, I found that the LCD worked – but there was still no activity light. The LED flashes once when the Kill-A-Watt is plugged in, but that’s it. It works though, so I’m not complaining.
For the moment, the wattcher.py script available from ladyada.net is the extent of the logging I’m doing. By default, it logs to a csv file every five minutes. There is also code for connecting to Twitter and to Google App Engine. Eventually, I’d like to log to MySQL and display the power usage right on my blog. Someday…
Anyway, Tweet-A-Watt is a pretty cool and possibly useful project. It’s on the expensive side if you go the kit route, but no matter how you build it, you end up with parts that can be used on other projects (mainly, the XBee chips and their adapters) if you ultimately decide that this project is not what it should be.
I was not able to attend CFUnited this year, simply due to the high cost of the event. This was unfortunate as it is supposedly an awesome conference. Fortunately enough for me, a new CF conference is taking place in Raleigh, NC on October 17th and 18th. Best of all? It’s a free event! I can afford free, even if it is 6 hours away.
The list of speakers and topics isn’t finalized, but the preliminary list is pretty promising. Sounds like it should be a good time and I’m sure to learn a lot! Unfortunately, though, it is the same weekend as another low-cost conference of equal awesomeness (CPOSC), which I will not be able to attend.
I passed this on some random road in New York state last winter. After thinking about it for a minute or two, I drove back to snap a photo. With Columbus Day approaching, I figured it would be a good time to share it. Kurt Vonnegut provides the caption.
“1492. As children we were taught to memorize this year with pride and joy as the year people began living full and imaginative lives on the continent of North America. Actually, people had been living full and imaginative lives on the continent of North America for hundreds of years before that. 1492 was simply the year sea pirates began to rob, cheat, and kill them.” – Kurt Vonnegut
Snapple Fact #680: “More Siberian tigers live in zoos than in the wild.”
That’s pretty much the most depressing thing I’ve ever read on the underside of a bottle cap.
Did you know that the Amazon MP3 Downloader runs on Linux? I didn’t. Generally, when I see a note stating that additional software is required on a website, I head for the hills figuring there’s no chance it will run in Ubuntu. Today, for some reason, I clicked to find out more about the “Requires Amazon MP3 Downloader” button next to the album I was looking at. Much to my surprise, they offer Linux support. Not the “here’s the source, good luck compiling it” kind of support, but rather the “here’s a .deb package, ready to install” kind of support. I was mighty impressed… for about a minute – the 32bit package is not a straight-forward install for 64bit users. Fortunately, it’s pretty easy to make the 32bit package work.

Of course, the fact that extra software is required to download purchased audio tracks doesn’t exactly thrill me, but it sure beats trying to run iTunes in Wine. The fact of the matter is that this is bare-bones, working software that actually runs on Linux:

Whether or not it turns out that tracks you have downloaded can be spontaneously deleted remains to be seen, of course
Recently, I came across an interesting “catch” when passing around a cfcatch structure. I created a function that would take a cfcatch struct and send out an email with the results formatted as I wanted them to be:
<cfcomponent output="false"> <cffunction name="sendCFCatchEmail" access="public" output="false" returntype="void"> <cfargument name="cfcatchStruct" type="struct" required="yes"> <cfargument name="emailAddress" type="email" required="yes"> <cfmail from="email@email.com" subject="Error" to="#arguments.emailAddress#" type="html"> <table> <tr> <cfoutput> <td>#cfcatch.type#</td> <td>#cfcatch.message#</td> <td>#cfcatch.detail#</td> </cfoutput> </tr> </table> </cfmail> </cffunction> </cfcomponent>
What threw me was that I kept getting the following error when passing a cfcatch struct to the function:
“The CFCATCHSTRUCT argument passed to the sendCFCatchEmail function is not of type struct.”
Huh?
The difficulty I was having was that when you dump a cfcatch, it identifies itself as a struct.

It took me a little while (and maybe some googling) to figure out what was going on. Doing an “isStruct(cfcatch)” shows that for some reason, cfcatch is not a structure. What is it then? Well, an “isObject(cfcatch)” shows that it’s an object… of some kind. The particularly odd part is that “Duplicate(cfcatch)” will return a structure, not an object. Weird, huh?
<cftry> <cfset answer = 3 / "t"> <cfcatch> <cfoutput> <h2>Standard cfcatch</h2> Is Struct: #isStruct(cfcatch)#<br /> Is Object: #isObject(cfcatch)#<br /> <h2>Duplicated cfcatch</h2> Is Struct: #isStruct(Duplicate(cfcatch))#<br /> Is Object: #isObject(Duplicate(cfcatch))#<br /> </cfoutput> </cfcatch> </cftry>

In short, I just ended up changing the expected type for the cfcatchStruct argument to be “any”. I could duplicate cfcatches before sending to the function, but that’s not optimal in the least, so I just let cfcatch pretend that it’s an object if that’s what it wants to be.
It is incredibly rare that I see a postcard on a store rack worth keeping, let alone have one arrive in my mailbox. The one I just got, however, was so awesome that I framed it and hung it up in my bedroom.
That way, no matter how bad my day might be I can come home to look at this postcard, think happy thoughts, and ask “Did I really frame a postcard about being rejected from jury duty?”
And with a smile on my face I can answer “Why yes, yes I have.”
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| « Dec | ||||||
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | ||||||
19 queries. 0.925 seconds