ColdFusion Struct Literals Fail Again

ColdFusion introduced CFML struct and array literals in CF 8.  They sucked.  Assignment only, no nesting, and the use of '=' for key-name pairs instead of ':', like every other language including other parts of CFML.  CF 8.0.1 fixed the nesting issue, but not the others.  I've been trying to figure out why it's an assignment-only construct since CF 8 was released, and today I figured it out.  It's stupid.  Take this code (which fails on CF8):

<cfset s = "cat,dog,bird" />
<cfset s = {
  first = listFirst(s),
  rest = listRest(s)
}/>

If you were to convert that to the old non-struct-literal syntax, it'd probably look like this:

<cfset s = "cat,dog,bird" />
<cfset temp = structNew() />
<cfset temp.first = listFirst(s) />
<cfset temp.rest = listRest(s) />
<cfset s = temp />

That's what Railo does (or the equivalent), but ColdFusion evaluates it like this:

<cfset s = "cat,dog,bird" />
<cfset s = structNew() />
<cfset s.first = listFirst(s) />
<cfset s.rest = listRest(s) />

This will obviously fail, because ColdFusion is reassigning the 's' variable too early in the process.  In most cases it doesn't matter, but not all cases.  Worse, it doesn't give you a useful error.  Instead, it says "Complex object types cannot be converted to simple values", which while accurate, is totally perplexing if you consider the original snippet.

Note that this is a ColdFusion problem, not a CFML one.  Railo compiles it correctly (and it doesn't share the assignment-only requirement either).  OBD doesn't support literals at the moment.

Edit 2009/04/07: revised some text slightly.

16 responses to “ColdFusion Struct Literals Fail Again”

  1. Sami Hoda

    Hey Barney, Are you providing these notes to Adobe?

  2. Sami Hoda

    Great to hear that.

    I think the wish list gets broadcast to the whole development team, which is both good and bad, because I'm not sure if any one person takes ownership of it.

    Waiting for the bug base as well. But, once the committees are setup, we can barrage members as well who are managing the specific area we find issues with.

  3. Sean Corfield

    Barney, are you sure those code fragments are right? The third fragment seems to assign to s and then overwrite it with an empty struct. I'm not quite sure what point you're trying to make here. Could you clarify?

  4. Joshua Frankamp

    Sean,

    It's about order of operations. The first fragment should be evaluated from the inside out, NOT the outside in. s should not be modified until the entire block has been evaluated. The third block looks strange because that is how CF8 decides to implement it. Just paste the first block into a test page on CF8 and think to yourself, why does this error?

    Think of a duck typed use case, like barney's example. s could be called, animals for example. He has a simple list representation as a starting point, but decides to transform it into a complex structure and… oh lets say he's in a cfc function body. Why go to all the trouble to var yet another variable to represent the same data in a different form, we arn't going to need the list afterward… GONK.

  5. Sean Corfield

    OK, that was completely unclear (to me). I didn't realize you were saying the first fragment didn't work! Yeah, then in that case, I agree that it's broken.

  6. Derek P.

    I absolutely hate the "=" syntax, what were they thinking!? I imagine the thought process was "easier for developers to 'get'", but I still think its absolutely unconventional.

    I wasn't aware you couldn't nest structs using literal syntax either, interesting.

  7. Elliott Sprehn

    Sigh, this does seem to be an extremely half baked feature. Hopefully once the CFML committee is up and running and there's a real standard for how the language should behave we'll be able to push Adobe to fix this stuff.

    I'd really like to see allowing quoted strings in the name part.

    { "Something With Spaces" = [ "a", "b", "c" ] }

    php, ruby, python, perl, groovy, javascript, as3 … Everyone has literal notation like this now that allows quotes and proper nesting.

    Why are we in the stone age? :/

  8. Elliott Sprehn

    Also, for that matter, why can't we pass literals as attribute values or directly in function calls?All the above languages also support that.

  9. Ben Nadel - At It Again at BarneyBlog

    [...] Ben Nadel posted another interesting code snippet this moring.  NEVER EVER USE IT.  It leverages a horrible bug in ColdFusion's implementation of struct literals that I've blogged about previously. [...]

  10. ColdFusion Struct Literals Are Not Thread Safe (CFML Ones Are) at BarneyBlog

    [...] lets you write some really nasty code, causes some weird bugs, and today I realized (through some handy errors on our production cluster) that there are thread [...]

  11. Adam Tuttle

    Barney, have you submitted this as a bug now that we have the public bugbase? I'd vote for it, and I know a handful of others that would, too.