An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

Help the CFML Advisory Committee!

May 18, 2009 ·

Lately, the committee has been looking at proposals to extend CFSCRIPT so that components can be written entirely in CFSCRIPT instead of requiring tags. Adobe has been the main driver for the proposals but other committee members have been providing their share of ideas and suggestions when we get stuck (or don't like Adobe's proposals). Right now, we have a pretty solid definition of how CFSCRIPT should work so that you can write entire components. Mostly it follows what you may have seen Adobe show off at conferences but Adobe is still making changes in response to feedback from the committee (and its own banks of prerelease testers, I'm sure) and some of Adobe's suggestions were considered vendor-specific by the committee. But we're stuck on a couple of tags that we're really struggling to define in CFSCRIPT. We'd like you to help us make some decisions here!First off, here's a simple component written using core CFML2009:
<cfscript>
import org.corfield.cfcs.*;

component extends="BaseComponent" {
   
   public any init( string fname, string lname, string addr ) {
      variables.fname = fname;
      variables.lname = lname;
      try {
         var country = getDefaultCountry();
         variables.address = new gov.usps.cfcs.Address(addr,country);
      } catch (any ex) {
         writeLog(text="Address failure",log="postal");
         throw(message="Invalid Address");
      }
      return this;
   }
}
</cfscript>
Extended core CFML2009 would allow the <cfscript> tags to be omitted (with rules about what is allowable outside component). Extended core also adds a few other useful constructs that are optional for vendors (but if they implement them, they should follow the committee's spec). You'll see import and new in here, as well as var appearing somewhere other than the top of the function. You'll also see that we've voted to include throw in core CFML with a function-call style syntax that allows attributes to specified like named arguments. We've generally followed that pattern for tags-as-script, so you can say, for example:
thread(name="mythread") {
   // your code here }
But we've run into some problems trying to solve this for cfmail and cfquery. The problem is that the body of these tags is treated specially. It isn't just code, it's text with embedded code. You can see the problem clearly in this example:
cfmail(...) {
I am text in the email!
but = i_am("a",functionCall());
}
In the tag-based version, it's easy to identify code: it all begins with <cf or is wrapped in # but in CFSCRIPT, code looks like regular text. Both cfmail and cfquery have nested tags and we can clearly put those in the tag-as-script body:
cfmail(...) {
   cfmailparam(...);
   cfmailpart(...);
}
Since CFML allows multi-line strings, we're considering adding a body attribute to cfmail and a sql attribute to cfquery so you could do this:
myMail = "Dear #fname#,

I am text in the email!"
;
cfmail(body=myMail) {
   // just code, including cfmailparam() etc }
We've reviewed a lot of syntax options and dismissed most as either unworkable for some technical reason or just downright ugly. What would you like to see for mail and query in CFSCRIPT? And, yes, we're still discussing cfmail vs mail. For some tags, the name without the prefix is likely to clash with existing user variables and functions - and may not be as easy to read. For example, which of these two are more obvious and less likely to cause compatibility problems with your code:
http(url="http://foo.com/",result=data) {
   httpparam(type="cookie",name="uid",value="42");
}
cfhttp(url="http://foo.com/",result=data) {
   cfhttpparam(type="cookie",name="uid",value="42");
}
So, input please! On both the syntax for mail and query specifically but also tags-as-script in general.

Tags: cfml-advisory · coldfusion

143 responses

  • 1 RobG // May 18, 2009 at 1:48 PM

    Maybe I'm oversimplifying things, or not clear on something, but my thought is this... why not just make those tags actual objects? Maybe create an instance of the cfmail object, then populate its properties with the various settings, and then execute it? Maybe that won't work with how CF does things, but it's an idea from a relative OO newbie. :)

    Rob
  • 2 Steve 'Cutter' Blades // May 18, 2009 at 1:52 PM

    For me, full CFScript implementation is one of the most exciting features announced for Centaur. I agree with your assessment of the 'cf' prefix on these functions, and think having a 'body' attribute makes sense for cfmail, and a 'sql' attribute for cfquery does as well. Simplifies things a great deal, especially since you can create multi-line string objects.
  • 3 Daniel Sellers // May 18, 2009 at 2:02 PM

    What if you treated cfmail and cfquery as objects and could specify their configuration with something like:
    cfmail.server = &quot;smtp.mymailserver.com&quot;;
    cfmail.to = 'test@test.com';
    cfmail.from = 'bob@nowhere.com';
    cfmail.mailerid = 'My Mailer';
    cfmail.mailParam('filePath');
    cfmail.mailPart(html){
    '&lt;p&gt;Paragraph'&amp; i &amp; '&lt;/p&gt;'
    }
    cfmail.mailPart(text){
    'Paragraph' &amp; i
    }
    cfmail.send();

    -or- cfquery:
    cfquery.dsn = 'dsn';
    cfquery.sql('select * from table Where id =' &amp; queryParam(i)');

    Hmm... now that I see that I am not sure if I like it. Maybe someone else can run with the idea a bit farther then I can. Of course you would have a default dsn in CF9 if I am not mistaken...
  • 4 Rick O // May 18, 2009 at 2:12 PM

    I suppose an E4X-style solution, with old-skool-style literal chunks, would be out of the running?

    result = &lt;cfmail&gt;same as it ever was&lt;/cfmail&gt;;

    qRecords = &lt;cfquery&gt;SELECT * FROM myTable&lt;/cfquery&gt;;

    fileContent = &lt;cfhttp&gt;...&lt;/cfhttp&gt;;

  • 5 Sean Coyne // May 18, 2009 at 2:17 PM

    My vote goes to body and sql attributes. That said why would anyone want to code it like this? This is precisely the syntax I hage loved avoiging by using CFML all this time.
  • 6 Sean Corfield // May 18, 2009 at 2:18 PM

    @RobG, @Daniel, we already reviewed a proposal for that (tags-as-objects) and no one on the committee liked it. There are problems with making such an implementation thread safe and you'd generally end up writing a lot more script code than the equivalent tags.

    Would you want to have to create a new object instance every time you sent email or ran a query?

    qry = new cfml.Query(dsn=&quot;dsn&quot;,sql=&quot;select * from table where id = :id&quot;);

    qry.queryParam(name=&quot;id&quot;,value=myId,type=&quot;cf_sql_integer&quot;);

    qry.execute();

    Remember that queries have both the record set returned plus all the metadata. Also you can't just have queryParam() as a function call in the SQL - it needs the context of the query 'tag' itself (which is why it's a nested tag). That means you're forced to use query parameters in the SQL string (either ? for a positional param or :name for a named param, for example).

    The substitution of parameters in the SQL is the ugliest part of any solution we've looked at so far...
  • 7 Sean Corfield // May 18, 2009 at 2:22 PM

    @Patrick, the nested tags have to be in { body } so that they are executed after the initial attributes are set up and can refer to the as-yet-unexecuted parent tag.

    @Rick, I proposed tag { ... } as a script construct to allow tags to embedded directly but the committee did not like it:

    &lt;cfscript&gt;

    // script code

    tag {

    &lt;query ...&gt;

    select * from foo

    &lt;/query&gt;

    }

    // back to script syntax

    Again tho', your suggestion would not handle nested tags which is where most suggestions we've seen so far fall down.
  • 8 Jon Hartmann // May 18, 2009 at 2:27 PM

    I'm actually really digging the idea of just making it an argument to the function, but using a syntax like &quot;@&quot; declaration above to note that its dynamically evaluated. The similar the syntax the better.
  • 9 Robert Gatti // May 18, 2009 at 2:46 PM

    I agree with Rick's idea of an in line E4X style of code. The one thing I hate about other languages is string concatenation when it comes to SQL or other multi-line strings that can have function calls/variables in them.
  • 10 Jeff Gladnick // May 18, 2009 at 2:54 PM

    Perhaps I am a luddite and swimming against the tide, but I am dreading full cfscript support by any CFML engine. The two main reasons are

    1) (selfish) - I hate it personally. I just plain dislike the appearance of it, and find the tag based version easier to read, easier to explain to newbies, and easier to work with...even if its slightly more verbose.

    2) (non-selfish) - I am afraid it will fork the language. Although many people are worried about OpenBD or Railo forking the language, I'm much more concerned about cfscript. I'm afraid there will be two classes of programmers - the elites using cfscript, and the new users using tag based syntax. A lot of people don't seem to think this is a problem, but I learned OO and MVC by looking at other people (the elites') code and open source projects. I think for people used to tag based syntax, trying to make this leap and learning cfscript is a bit harder
  • 11 Sean Corfield // May 18, 2009 at 2:57 PM

    @Jeff, there are a *lot* of CFers who want CFSCRIPT extended and many people feel that the tag syntax is a barrier to entry from other languages / backgrounds.

    No one will force you to use CFSCRIPT and it won't add features that you can't do from the tag syntax. It just provides an alternative for people who don't like tags.

    It might be enough to tempt new developers to CFML (there's a lot of evidence that tag syntax is considered a big negative for CFML by many people outside the CF community).
  • 12 RobG // May 18, 2009 at 3:05 PM

    I agree with Sean. Let's remember that cfscript is a convenience; it's hardly mandatory. As people come to CF and learn the tags, they can choose to migrate to cfscript at whatever pace is comfortable.

    Where I work now, their stuff is about 90% cfscript. When I first started, it looked alien and intimidating. A month later, I was totally into it and am converting my own code to cfscript (in my own projects) because it's so much quicker and simpler than tags.
  • 13 Peter J. Farrell // May 18, 2009 at 3:37 PM

    @Jeff, Just wanted to mention that I'm one of those people that does not really care for cfscript, however I do see it as something that needs to be a) fully supported or b) removed entirely. Removing it breaks code (meaning it's not backward compatible - BC) and therefore really not a good thing here. And @Sean is right, most non-CFMLers see tags as a fundamental negative to CFML as a langue. For example, I think Java peeps see it like the big bad nasty thing called JSP - which most Java-ites hate.

    All in all, I'm the newest member of the committee and I'm trying to wrap my head around the cfmail / cfquery problem. However, I think we'll find a nice and elegant solution given enough eyeballs look and think about the possible solutions. While I wasn't on the committee at the time when &quot;tags as objects&quot; was proposed, I'm in agreement with the committee members that &quot;tags as objects&quot; just don't strike me as the greatest solution.
  • 14 Patrick McElhaney // May 18, 2009 at 3:38 PM

    Cfquery(name=&quot;foo&quot;,datasource=&quot;db&quot;,@body=[&quot;select * from table where category = &quot;,cfquerparam(...), &quot; order by foo&quot;])

    That is, you pass a list of tag literals (cf*(...)) and text nodes (strings).

    If there are no nested tags you would have an array containing a single string. You could allow a string as a shortcut, which gives you what most people probably prefer when possible.

    Cfmail(to=...,from=...subject=...,@body=&quot;hello world&quot;)

    You could also have a udf create the body.

    Cfhttp(@body=paramsforwebservice(uid,keyword,maxresults))

    -------

    @Sean, I see you point about child tags needing access to the parent's attributes. I think that could be done. cfqueryparam(...) looks like a function but is really just a different syntax for &amp;lt;cfqueryparam ...&amp;gt; Likewise, @body=[...] looks like a function parameter, but it's really just another way of specifying the nodes between the open and close tags.
  • 15 Jeff Gladnick // May 18, 2009 at 3:51 PM

    @Sean - Yeah... I am aware that I represent the minority here.(although this would be good for a poll, even though I would imagine that people keeping up with blogs would skew the results a bit..)

    Clearly if I create my own stuff from scratch, I would need to use CFSCRIPT. But if I need to integrate open source projects, or other peoples libraries, I personally don't like the hodge-podge of cfscript and normal tag based langauge.
  • 16 Dale Fraser // May 18, 2009 at 4:02 PM

    I beg the CFML Advisory Gods

    to not let them introduce things such as

    dump;

    it should be

    dump();

    there are other such examples. We will have to put un with inconsistancies like this forever if we allow them to introduce them.
  • 17 Aaron Greenlee // May 18, 2009 at 4:02 PM

    I just played with some 'dream code' and after evaluating a few ideas, I second Jon Hartmann's post.

  • 18 Adam Ness // May 18, 2009 at 4:08 PM

    One final observation: I find it mildly amusing that while most other platforms are moving from imperative to delcaritive formats (.Net -&gt; WPF/XAML, ActionScript -&gt; MXML, Java -&gt; FXScript ), CFML seems to be trying to swim upstream in the other direction.
  • 19 Jeff Gladnick // May 18, 2009 at 4:17 PM

    @Peter - I tend to agree with that. Either support it or end it. I do wish it had never come into being in the first place, but now that its here... Also, congrats on your appointment to the committee, I cannot think of a better person to represent the CF community.
  • 20 Chris Phillips // May 18, 2009 at 4:30 PM

    Sean,

    In answer to &quot;Would you want to have to create a new object instance every time you sent email or ran a query?&quot;: Sure.
    I think the syntax you used as an example makes way more sense than the proposed &quot;use function declaration syntax as function execution&quot; syntax.
    Is there any precedence for the syntax that is being proposed?
    Also, syntax completion seems like it would be very slick for the tag-as-object option. If all the methods were chainable, you could do it all on one line.
    And my suggestion would be that after you executed that, the &quot;sql&quot; variable would have a &quot;result&quot; and &quot;metadata&quot; key for the last run of it.

    So something like this would work:
    qry = new cfml.Query(dsn=&quot;dsn&quot;,sql=&quot;select * from table where id = :id&quot;).queryParam(name=&quot;id&quot;,value=myId,type=&quot;cf_sql_integer&quot;).execute();
    dump(sql.metadata);
    dump(sql.result);

    Maybe the records and metadata should be grouped in a &quot;result&quot; struct... Then dump(sql.result) would display the records and metadata like the current cfdump of a query does.
  • 21 Sean Corfield // May 18, 2009 at 4:50 PM

    @Adam, the main reason that Adobe has talked about enhancing CFSCRIPT is precisely to keep CFers using CFML instead of them going off and using Groovy or some other more script-y technology. If enhanced CFSCRIPT keeps more developers using CFML, it's a good thing, surely?

    @All, interesting to see several people are not opposed to the object syntax. Maybe we'll resurrect that discussion on the committee.

    @Dale, not sure where you got that dump; example from? What would it do? Even dump(); makes no sense. Did you mean something like:

    writeDump( var=myThing, label=&quot;This is my thing on drugs&quot; );

    (which, in fact, is what the committee plan to add - plain ol' dump() is too likely to conflict with existing code where people have invented their own custom workarounds for the lack of a dump tag in CFSCRIPT).
  • 22 Daniel Sellers // May 18, 2009 at 4:51 PM

    @Sean Yeah I see your point with cfquery in particular.
  • 23 Mark Jones // May 18, 2009 at 5:03 PM

    I absolutely support full script support, but share some concerns. If you're a scripter, you can always &lt;cfscript&gt; and go. Without tag {} it's impossible to go the other way. Why not?

    Apparently I'm another vote for E4X-style, at least as an option.

    boo = &lt;cfquery datasource=&quot;&quot;&gt;...&lt;/cfquery&gt;

    At that point, there would be no need to limit such syntax to only a few tags, but it might take a second to figure out if the other text is content or script... which is a strike AGAINST allowing the removal of &lt;cfscript&gt; tags.

    As far as actual script goes, I see nothing wrong with Sean's object example above. If you're adding this FOR people who are used to doing queries that way, why not do it that way?

    No matter what, you'll end up annoying people who *will* have to learn multiple syntax for at least a few things. Saying you don't &quot;need&quot; to know script is useless if you're given pre-written code to debug.

    With all that in mind, please, PLEASE be sure to add a heredoc / cfsavecontent syntax so we don't have to constantly escape quotation marks when building long strings!
  • 24 Mark Jones // May 18, 2009 at 5:24 PM

    I hate to continue the drift we're taking from the original question, but:

    &lt;cfdump&gt; vs writeDump()

    is confirming that we'll have two potentially entirely different sets of commands to memorize.

    One more query/mail option that hasn't come up: look to &lt;cfimage&gt;

    eml = EmailNew( {tag attributes} )
    eml = EmailBody(&lt;&lt;&lt;END
    body here in #subversive# heredoc fashion
    END;);
    EmailSend( eml );

    Ugly as heck, but there's precedent.
  • 25 radekg // May 18, 2009 at 5:41 PM

    @Adam Ness: mxml, wpf/xaml does not contain processing logic, it is only a visual layer that gets processed by c#/vb, as3. I am not sure about fxscript but I would assume it is the same.
  • 26 Peter J. Farrell // May 18, 2009 at 5:50 PM

    @MarkJones, I don't think it's clear in this blog post on the rules in which the removal of CFSCRIPT tags can occur. Sean can correct me if I'm wrong since I could be interpreting the specs as they are written currently (and yes, we're discussing a bunch of stuff that is not completed yet). From what I can tell, really the removal of the opening and closing CFSCRIPT tags would only be valid in files that end in .cfc and that the code within following a certain format. Also, we are discussing a CFSAVECONTENT version in CFSCRIPT, but at this time don't have an example that we all like so far because it will probably following a similar format to what is decided upon for CFMAIL and CFQUERY (same problems).

    @Dale, also CFLOG will probably be writeLog() to be inline with the syntax that Sean mentioned about writeDump(). I feel this is in perfect line with writeOutput() which CFSCRIPT already has.



  • 27 Sean Corfield // May 18, 2009 at 5:52 PM

    @Mark, the committee was almost unanimous that tag { ... } was just too ugly. Almost = I was the only one in favor of it.

    There will be a small handful of naming differences between tags and their script equivalent, done purely in the name of not breaking existing code. However, consider that cfoutput effectively becomes writeOutput() in script today and it &quot;makes sense&quot; that cfdump becomes writeDump() and cflog becomes writeLog() - in the latter case there's already a built-in log() function and in the former, lots of people have rolled their own dump() function. We don't want to break that code!

    The &quot;ItemAction&quot; style of cfimage (and other parts of the language) leads to a horrible proliferation of built-in functions and that is considered undesirable.

    Adding true heredoc strings in some way would be useful tho' (I believe it has come up in discussions but never garnered much support).
  • 28 Peter J. Farrell // May 18, 2009 at 6:07 PM

    @Jeff, thanks for your kind words re: my invitation to the committee.

    @All, CFMAIL / CFQUERY as objects would work because the nested information / tags is more restrictive. However, I still don't think that work so well for CFSAVECONTENT as the real power comes from being able to save the content between the opening and closing tag. Yes, a lot to ponder.

    @Sean, yes at the time a vote was taking re: the tag { } syntax -- nobody did like that except I wasn't part of the committee at the time. Dare I say it might make some fugly looking code? However, on the flip side it does solve some problems (especially nested tags). Me does thou think I am going to take some complicated Mach-II code and see what it looks like in some of the new CFSCRIPT. It might give us a more real world view into what current tag based code would look like (versus an example).
  • 29 Adam Ness // May 18, 2009 at 6:09 PM

    @Sean - If you're building up a whole new language syntax (cfscript) to keep people using the language that you already have (cfml), isn't that kind of backwards? Wouldn't it be better just to expose the platform that underlies your existing language to people who want to develop in a different language? Make it possible for someone who wants to write in java to just

    import coldfusion.*;

    CFScope variables = new CFScope();
    CFTemplate index = new CFTemplate(&quot;index.cfm&quot;);
    response.write( index.process( variables ) );

    @Radekg - Actually, Mate and several other Flex projects are using the declarative nature of MXML to apply to non-visual processing. Hibernate, nHibernate, and LINQ attempt declarative database access on Java and .Net platforms. There are more than a few non-visual declarative projects moving quite happily along.

    There are certain operations in ColdFusion, such as CFQuery which are more declarative than imperative. These are the points which tend to be sticky when converting whole-hog to CFScript. I tend to think it's best to keep the declarative parts declarative, thus my thought that we should stick with the e4x style if it's strongly desired to use cfquery within a cfscript block.

  • 30 Peter J. Farrell // May 18, 2009 at 6:15 PM

    @Seam/Mark, I totally forgot about heredocs (it's been a while since I've used that in Bash). Yes, that could be interesting, but does it solve any of the problems about? Haven't formed an opinion yet. For those that don't know about heredocs, here is the Wikipedia article for your reading pleasure:

    http://en.wikipedia.org/wiki/Heredoc

    Last, I simple extension to the current using of string literals could be &quot;&quot;&quot; (three double quotes) or ''' (three single quotes) as a heredoc. And yes, that is exactly like Python does.
  • 31 Sean Corfield // May 18, 2009 at 6:18 PM

    @Adam, CFML already has cfscript - we're hardly &quot;building up a whole new language&quot;. Merely adding things that CF developers have been asking for (for years, I might add).

    The example shown above has a CFSCRIPT equivalent today. It just isn't as expressive nor as clean - createObject() calls instead of new, lack of type specification in function declaration etc.
  • 32 Adam Ness // May 18, 2009 at 6:31 PM

    Honestly, the more I mull it over, the more I think I like the e4x syntax. It could even allow you to replace the writeOutput() function with just &lt;cfoutput&gt;...&lt;/cfoutput&gt;. Honestly, despite my original reservations, if I could write a whole file in cfscript, and just &quot;shell&quot; out via e4x to CFML when it made sense, I would probably start coding in CFScript.

    Heredoc in such a world would be accomplished by:

    var a=&lt;cfsavecontent&gt;&lt;cfoutput&gt;
    &lt;h1&gt;I'm a heredoc&lt;/h1&gt;
    &lt;a href=&quot;#linkURL#&quot;&gt;#linkTitle#&lt;/a&gt;
    &lt;/cfoutput&gt;&lt;/cfsavecontent&gt;;

    Of course, the downside is that a lot of folks who are coming from languages where e4x doesn't exist will be massively confused when arriving. I know I was when I started using AS3.
  • 33 Mark Jones // May 18, 2009 at 6:34 PM

    If a heredoc syntax is used consitantly, it could solve some issues. (It also makes for nicely formatted queries.. if he tabs below come through)

    query(&quot;&quot;&quot;

       SELECT * FROM table
       WHERE
          id = #queryparam(id, &quot;cf_sql_integer&quot;)#
       AND   catid = 2

    &quot;&quot;&quot;);

    ... The param part obviously needs some work to differentiate it from a simple function call / content insert. You could try delimiters other than #, but that's pretty horrible.

    Maybe allow for &lt;cfqueryparam&gt; tags in the body (thus allowing copy/paste of code between tags and script) *and/or* the ? placeholders with additional parameters? Tag syntax is perfect for saying &quot;this data goes here&quot;, though I understand how mixing in tags willy-nilly is itself problematic. I'm hoping the two approaches complement each other instead of clash.
  • 34 Peter J. Farrell // May 18, 2009 at 6:45 PM

    @Adam, I honestly don't see the benefit to expose CFML to be written in Java as you mentioned unless you merely are looking for an academic exercise. Also, looking from the CFML engine perspective, I hardly see how this can be accomplished because all three engines are architectural different behind the scenes based on my conversations with people about Railo, OpenBD and Adobe CF.
  • 35 Mark Jones // May 18, 2009 at 7:04 PM

    @Sean, Point taken about name differences. I know it's inevitable. And I agree 100% about the function proliferation; the image functions alone are a mess. That's another argument for rolling such things up into objects. If we can write cfcs, why not have cfc-like behavior built into the language for tasks that make sense?

    One downside is that what CF currently calls a Query is really a recordset... and there's not much we can do to get around that, what w/ QueryNew() et al.
  • 36 anthony // May 18, 2009 at 7:28 PM

    @Sean, I think that dump() makes sense as a function. I don't think you should worry about the handrolled dump() functions, it's likely people are using them more in development than in production code. I do think that since a lot of cfscript is just the tag without the cf (cfif -&gt; if, cfswitch -&gt;switch, etc.), wouldn't it make sense to make the cfscript version of cfdump just dump?
  • 37 Patrick McElhaney // May 18, 2009 at 7:47 PM

    You say this is text embedded with code.

    cfmail(...) {
    I am text in the email!
    but = i_am(&quot;a&quot;,functionCall());
    }

    If you want to embed code in text, you could try the traditional route.

    cfmail(...) {
    I am text in the email!
    #setVariable(&quot;but&quot;, i_am(&quot;a&quot;,functionCall()))#;
    }

    Or you could embed it in a body attribute:

    cfmail(..., @body= &quot;I am text in the email!&quot; &amp; setVariable(&quot;but&quot;, i_am(&quot;a&quot;,functionCall()))


    Or you could not embed code in text when there's no good reason to do so.

    but = i_am(&quot;a&quot;,functionCall());
    cfmail(..., @body=&quot;I am text in the email!&quot;);




  • 38 adam ness // May 18, 2009 at 7:50 PM

    @Sean I think you misunderstood. I was suggesting calling CFML from java/groovy/jpython/scala, not extending cfscript to act more like java.

    If I wanted a language with braces and semi-colons and 20 lines of code to call a database, I wouldn't use ColdFusion. There are plenty of other solutions out there that fit those requirements.
  • 39 Tony Nelson // May 18, 2009 at 8:14 PM

    I'd prefer treating cfmail and cfquery as objects. Although it might be a little more verbose, I think it reads a lot cleaner and the intent is a lot more obvious.

    email = new Email()
    email.to = 'joe@email.com'
    email.from = 'bob@email.com'
    email.subject = 'hello',
    email.message = 'just saying hi!'
    email.addAttachment('c:\file.pdf')
    email.send()

    Either that or something like:
    email = new Email({to='joe@email.com',from='bob@email.com',subject='hello',message='just saying hi'})
    email.send()

    Actually I'd probably prefer a combination of the two, where optional arguments would call their corresponding setters if passed in. That way people could pick their way of writing it in a single statement or multiple lines.

    Just curious, but why are people suggesting using cfmail(@body='') instead of just cfmail(body=''). If you forget about how the tag currently works, is there a reason why the body attribute would be considered different from the rest of the attributes?

    As for cfquery, I don't think having to explicitly add parameters via query.setInteger('id',id) is all that bad, especially if you consider Hibernate's popularity. Plus it really enforces you to you cfqueryparam, which only encourages good practice.

    As for cfsavecontent, it's kinda like writeOutput() in that it just wraps stuff (cf/html) in tags, so why not treat it the same?
    test = cfsavecontent(
    'hello world, '+now()
    )
  • 40 John Farrar // May 18, 2009 at 8:26 PM

    I campaigned for getting cfrethrow, cfdump, and other tags added as script for years and versions! Yet, I am not 'excited' about all the new script. I just wanted a complete core... it's nice to have more in script but have to agree with some others that this is not a priority for me. Never was. All I ever wanted was the basic core features complete. Beyond that you guys seem to have a good idea of how to do these things so far IMO.
  • 41 anthony // May 18, 2009 at 8:45 PM

    @Sean, actually after thinking about it, writeDump does make more sense if the writeLog and writeOutput are in cfscript.
  • 42 Christopher Vigliotti // May 18, 2009 at 8:57 PM

    +1 for the body and sql attributes

    Also, since there is already a standard for writeOutput and writeLog please consider extending that to writeQuery and writeMail. perhaps another prefix for query and mail other than &quot;write&quot;...but something that describes what the function is doing (as opposed to using the &quot;cf&quot; perfix).

    I'm stoked about full CFSCRIPT support, thanks to everyone that is working on this!
  • 43 Adam Ness // May 18, 2009 at 9:05 PM

    @Peter - I'm coming at it from the perspective of what makes ColdFusion a good platform to program on, whether it's Railo, OpenBD, or ColdFusion. There's the CFML syntax, which is powerful and useful for making declarative database calls, LDAP Queries, WebService invocations, and templating HTML (or other XML-Like languages), and a consistent, out of the box API for talking to all of these sources. There's also the underlying database pooling, session, login, and page request/response mechanism which is a powerful platform to build on. Providing the cool parts of the ColdFusion platform to other languages would be nice, if not unique in the world of web frameworks.

    However, what' you're describing with these CFScript changes are to take what is a small scripting language, which can accomplish a subset of what can be done with CFML, and turning it into a first class language, sitting on top of the ColdFusion platform. Furthermore, it's a new language, with the typeless weaknesses of JavaScript and none of the advantages of Java much less Jython or Groovy. What's the goal? Does something written in pure CFScript even qualify as CFML or ColdFusion anymore, especially if all the things which are simple in CFML require large blocks of code, and now consist of massive blocks of string concatenation?

    The small changes, the ability to use new and import are very nice. I'd absolutely love to see a corresponding &lt;cfimport package=&quot;...&quot; /&gt; tag. But there are just some things that CFML is better for, and for those things, it makes sense to use CFML, rather than try to over-engineer a way to accomplish the same thing in a semi-colon/braces language.
  • 44 andy matthews // May 18, 2009 at 11:15 PM

    I'd love a ternary function in cfscript

    var value = (one &lt; two) ? true : false;

    I just this all the time in javascript and it's so clean and beautiful.
  • 45 Eivind // May 18, 2009 at 11:21 PM

    Are you planning to take steps in direction of more OO ?

    It's really amazingly stupid that it's

    ImageGrayScale(img), ImageNegative(img) etc polluting the top-level global namespace when there's no compelling reason why img couldn't be a object, with methods called the normal way (i.e. img.negative()) bonus-points if I can do myimage extends=&quot;cf.core.image&quot;

    In a related wish; could we have OnMissingProperty to go with OnMissingMethod ?

    Would make it possible to make prettier beans that behave like structs, though aren't.

    (i.e you could make person.name work even if &quot;person&quot; is an object)
  • 46 Aaron Neff // May 18, 2009 at 11:22 PM

    IMO - since &lt;cfscript&gt; is allowed within cftags, then the reverse (tag{} within script) should also be true. +1 for tag{}
  • 47 Sean Corfield // May 18, 2009 at 11:46 PM

    @Andy, yes, the committee has voted that ? : be considered a core operator (and it's already supported by Railo).
  • 48 Sean Corfield // May 18, 2009 at 11:46 PM

    @Elvind, yes, I think the 50+ image methods are a monstrosity.
  • 49 Sean Corfield // May 18, 2009 at 11:48 PM

    @Adam, when you say things like &quot;typeless weaknesses of JavaScript and none of the advantages of Java much less Jython or Groovy&quot; it's hard to take you seriously. The advantages of Python and Groovy come from the dynamic, typeless nature. It is Java that is weak here.
  • 50 Ben Pate // May 19, 2009 at 12:25 AM

    Great discussion! I'd post a longer thread, but I think I've already seen everything I'd ask for in everyone else's posts. :)

    My votes:

    +1 for ternary operator
    +1 for not polluting namespaces (damn image tags)
    +1 for keeping tag definitions simple.
    +1 for body and sql attributes

    There is one thing I didn't see here (that is also NOT my original idea) that I'd love to see considered:

    I just hate having to put &lt;cfscript&gt;&lt;/cfscript&gt; around every block of code. Is it possible (and reasonable) to add a new file extension such as *.CFS that assumes that the entire contents of the file are CFSCRIPT? I would really like to see this because it would help identify pages that are ENTIRELY script, as opposed to pages where I'm generating some HTML output.

    @Sean: What about closures? I've seen your sample code that hacks closures into CF, but with all of these new features going in to CFSCRIPT, closures seem like a logical next step -- yes?
  • 51 radekg // May 19, 2009 at 1:45 AM

    @Adam Ness: xaml nor mxml is not a programming language and they can't do much without c# or as3 behind them. Hibernate and nHibernate use XML for describing the objects, LINQ is part of C# specification. &quot;Mate and several other Flex frameworks&quot; are implemented in AS3 and just expose their functionality with MXML. You're simply not right.

    I really have no idea how CFML committee is going to solve the problem. Here are my thoughts:

    - tag() {} looks like a simple function declaration and provides incosistency into the language
    - e4x, yeah, that's the closest one to me but it has two issues, once tags are implemented as e4x the road is closed for xml in the future, second - i'm not sure how compilers would deal with non XML nature of CFML.
    - converting everything to objects and using body or sql attributes doesn't look like a good approach, it kills the simplicity of CFML and the ability to mix conditional processing with sql/mail body/saved content.
  • 52 Marcel // May 19, 2009 at 1:53 AM

    component a extends=&quot;BaseComponent&quot; is the only thing I do not like at all there, why not
    component a extends BaseComponent or
    component a : BaseComponent I don't like quotes in the definition at all for readability, would prefer a more AS3 definition style.
  • 53 Justin Carter // May 19, 2009 at 3:05 AM

    I'm liking the E4X style expressions the most, and also another +1 for tag { ... }. The main reason for these is support for custom tags (or just being flexible and supporting tags in general!) - custom tags don't have a script equivalent and probably never will, but we still need a way to use them (or any tags) effectively inside a script block, IMO.

    If a component is written in script only, then not being able to use any tags inside it could be a disaster waiting to happen. For e.g. in ColdExt I use a custom tag to configure the library which should go in onApplicationStart() in application.cfc. Not having a way to break out of &quot;full script&quot; mode would prohibit the use of this custom tag and force me to write another configuration method, or force me to say &quot;this tag library isn't compatible with an all script application.cfc&quot;. You could say this is just bad design on my part, but it is an example of what could happen in the real world, and yet with the current flavour of CFML engines and cfscript implementation this problem does not exist!

    So if there are situations where tags cannot be used, developers could either rush in and use full script only to find they want to use a tag and have to rewrite parts of their CFC, or perhaps just avoid full script implementations due to it's shortcomings.

    Food for thought? :)
  • 54 Adam Cameron // May 19, 2009 at 3:08 AM

    Hi Sean
    Cheers for raising this discussion with the community, it's an interesting and important one, and I think it's good to get input from those using the language before any unilateral decisions are made about the direction of the language.

    To answer your specific questions, I think the object-based approach for mail &amp; query (etc) is fine, and the best approach (of many) I've seen attempted / suggested. What was the basis for resistance for the committee?

    I think writeDump() is a mistake. People will have dump() UDFs implementing &lt;cfdump&gt;, but if you ask them I imagine they would have no problem refactoring their code for a ideally-named dump() in-built function rather than having to move forward with a sub-optimally-named writeDump(). It's also a minor re-factor because there's almost no chance differences in the implementation will cause knock-on issues with how it's being used. Backwards compat should not get in the way of moving forward in the best direction.

    I don't think that any script-friendly implementation of CF functionality should have &quot;CF&quot; prepended to the name. It's a requirement for the way the tags are distinguished from other next, but it's ugly. No need to replicate that ugliness if it's not necessary. In your on example, I see no problem with

    myHttpReq = new http(etc);

    I'm sure I speak for everyone where I welcome any other questions / polls from the committee along these lines.

    Thanks!

    --
    Adam
  • 55 Steve 'Cutter' Blades // May 19, 2009 at 4:01 AM

    How is the following E4X like?

    var myMail = &lt;cfmail to....&gt;This is the Body&lt;/cfmal&gt;

    An E4X like implementation might be more like:

    var someResult = new cfmail({
    to: sendTo,
    from: sentFrom,
    body: 'This is my body',
    cfmailparam:[{
    name: 'prm1',
    value: 'first value'
    },{
    name: 'prm2',
    value: 'second value'
    }]
    });
  • 56 Tom Chiverton // May 19, 2009 at 4:25 AM

    I vote for .body= (or .sql= in the case of queries).

    If multiline literals are allowed, it shouldn't look too messy.
  • 57 Marko Simic // May 19, 2009 at 4:42 AM

    I would never try to reinvent the wheel if that is not necessary. So, either I don't have all information (almost certain) or you are trying to reinvent the wheel :)

    //place in constructor only general settings, not content-specific
    mail = new cfmail(host,port,username,pass);
    mail.subject='';
    mailparam = new cfmailparam();
    mail.params = mailparam;
    mail.send();

    etc...etc...as is in all modern OO languages.

    or nest it between brackets

    mailparam = new cfmailparam();

    mail = new cfmail(host,port,username,pass){
    subject='',
    params = mailparam
    } //auto-send

    Same aproach I would user for cfquery

    qrytest = new cfquery(datasource,dbtype,username, pass);
    qrytest.sqlstring = &quot;&quot;;
    qrytest.execute();

    or

    qrytest = new cfquery(datasource,dbtype,username, pass){
    sqlstring = &quot;&quot;
    } //auto exec


    Question:
    Why you use quotes on base component name:
    component extends=&quot;BaseComponent&quot;
    why not
    component extends BaseComponent

    (public/private/protected) component_name ?

    Thank you for your effort.
  • 58 Mark Jones // May 19, 2009 at 5:45 AM

    @tnelson The point of cfsavecontent is that you can build large blocks of content without worrying about string concatenation or quite escaping. Your example would still require both and is no different from the same code without the savecontent call:

    test = 'hello world, '+now()

    Try to build the content of, say, an HTML-formatted store receipt email by that method. Hello, ASP VBSCRIPT.
  • 59 David Hammond // May 19, 2009 at 6:42 AM

    I am one of those that wish cfscript never existed. Years ago, I loved the idea of cfscript, because it looked like my beloved javascript and allowed me to create UDFs. My problem now, though, is that having two different syntaxes for doing the same things ends up creating messy-looking code. How to deal with a development team where one person only likes cfscript and one person only like tags?

    With that in mind, I am most interested in the idea of making cfmail and cfquery into objects that can be used in cfscript (or in cfml for that matter). Would it mean more code for some things? Yes, but in some cases it just makes more sense to deal with things as objects, and in most other cases the tag syntax for cfmail and cfquery works better anyway. And if one of the stated goals of cfscript support is to attract developers from other languages, why come up with a new, unfamiliar way of doing things when the methods of dealing with objects is very comfortable to most developers? Just by 2 cents.
  • 60 TJ Downes // May 19, 2009 at 7:01 AM

    Object syntax. Just makes sense.
  • 61 Charlie // May 19, 2009 at 7:22 AM

    What about something like this? Anything in a WriteOutput() is captured as part of the query, everything else is just processing, so you have the whole language at your disposal like in &lt;cfquery&gt;.

    query(datasource=&quot;DSN&quot;, name=&quot;MyQuery&quot;) {
       WriteOutput(&quot;SELECT * FROM Table&quot;);
       WriteOutput(&quot;WHERE Column LIKE #QueryParam(value='#MyValue#%', sqltype='cf_sql_varchar')#&quot;);
       for(i=1;i&lt;10;i++) {
          WriteOutput(&quot;OR Column2 = '#i#'&quot;);
       }
       WriteOutput(&quot;ORDER BY Column ASC&quot;);
    }
  • 62 Mike Kelp // May 19, 2009 at 7:46 AM

    Personally, I find this whole debate about continuing and completing the cfscript language pretty unnecessary. I came from a background of nothing but scripting languages and am very familiar with how many languages have dealt (or not dealt) with the simplicity of tags within scripting only to run into one reality. If you're embedding tags within script, why not enclose the script within a tag instead. I don't see what's so verbose about having a script tag and closing it when you need to use functionality that is far better used via a tag.

    Furthermore, let's admit another reality which is that cfscript was never well-designed to begin with, so building on top of it this way really isn't going to make it a good language to work in. Why the heck would you even care to use cfscript 100% of the time when you could use a good scripting language like python, java, groovy, or almost any other scripting language where the designers of the language were trying to build a good scripting language from their inception.

    My personal suggestion would be drop cfscript completely and support a cfscript tag with a type attribute that would support any platform supported scripting with a base library of objects for mail, query, etc. Whether the server is built on .Net or Java, that would give you many languages to script in that are actually good at scripting as opposed to the handicapped cfscript we have that I argue will only begin to look more and more like the others anyway.

    Lastly I'll mention that the argument that ultimately won me over from the script language mentality I was in when I began cf is that even if you claim that a scripting language is too verbose (which is quite debatable for many real-life instances), it is far more complicated at the translation level. A key factor in language complexity and the work that goes into a developer understanding a page of code when they open a file is the number of distinct language constructs. Tags handle many of the situations that scripting handle with a single tag-attribute construct. They handle named arguments, optional arguments, containment (for looping, string management, try-catch, switch cases), and much more that all require an specific syntax within scripting.

    My two cents became 18 cents so I apologize for spilling my thoughts too much. However, you did ask for it hehe.
  • 63 Ryan Heldt // May 19, 2009 at 8:03 AM

    Hey Guys -- I understand this is a complicated problem and I wish the committee the best of luck. My one comment would be whatever you decide to do is to be consistent. One of the biggest gripes I have with CF (if you can call it that) is lack of consistency in places.

    For example, there are at least three different attributes for returning results from tag-based operations. cfsavecontent is variable, cfquery is result, and cfdirectory is name. So, I kind of cringe a little when I see a functions like cfmail() or cfhttp(). Why not just mail() and http()?.

    With that said, I really don't see a problem in just putting your body in a variable first, for example:

    var strBody = &quot;

    Dear Sir:

    All your base are belong to us.

    The Management

    &quot;;

    Then call your function:

    mail(to=&quot;foo@bar.com&quot;, from=&quot;bar@foo.com&quot;, subject=&quot;Notification&quot;, body=strBody);

    Of course, this doesn't let you do multipart e-mails very easily, so maybe a mailpart struct or something could be alternatively fed in. Just a thought.
  • 64 Andy Sandefer // May 19, 2009 at 8:25 AM

    This is a big step forward in terms of inviting more developers to sit down and eat at the ColdFusion table.
    If that is one of the primary goals of doing this with cfscript (and let's face it - growing the developer base is THE primary goal of this) then I'm all for voting for whichever solution is going to get us to that end. We are a Java powered solution so why not make the syntax as Java like as possible? Why is this such a debate?

    Properties props = new Properties();
    props.put(&quot;mail.smtp.host&quot;, &quot;my-mail-server&quot;);
    props.put(&quot;mail.from&quot;, &quot;me@example.com&quot;);
    Session session = Session.getInstance(props, null);

    try {
    MimeMessage msg = new MimeMessage(session);
    msg.setFrom();
    msg.setRecipients(Message.RecipientType.TO,
    &quot;you@example.com&quot;);
    msg.setSubject(&quot;JavaMail hello world example&quot;);
    msg.setSentDate(new Date());
    msg.setText(&quot;Hello, world!\n&quot;);
    Transport.send(msg);
    } catch (MessagingException mex) {
    System.out.println(&quot;send failed, exception: &quot; + mex);
    }
  • 65 Andy Sandefer // May 19, 2009 at 8:35 AM

    Speaking of Objects - Hal Helms where are you and why have you not solved this debate yet?
  • 66 anthony // May 19, 2009 at 8:41 AM

    @Cutter, I think you have that backwards. e4x is ecmascript for XML (http://en.wikipedia.org/wiki/ECMAScript_for_XML). Your example is json.
  • 67 Mike Kelp // May 19, 2009 at 8:42 AM

    Woops....my last comment should have said &quot;even if you claim that a &lt;i&gt;tag&lt;/i&gt; language is too verbose&quot;

    Sorry, but realized that wouldn't make much sense.
  • 68 Bagar // May 19, 2009 at 8:51 AM

    I don't like the idea of usingE4X-style. If we are talking about ugly vs pretty code, this is ugly: result = &lt;cfmail&gt;same as it ever was&lt;/cfmail&gt;;

    CFSAVEVONTENT is a huge issue, the buggest issue inside cfscript I believe, because there are no parameters passed in. I think the only solution there is brackets - which I like a lot. I believe it would solve CFQUERY as well. like this:

    I prefer the {} curly brackets. Most hard core languages use {} syntax in their functions. I believe this would solve all of the nesting issues paces with wrapper-type tags, CFSAVECONTENT, CFMAIL, CFQUERY, etc. The primary content of these tags should NOT be an attribute, it should be the body of the function inside the {} curly brackets.

    I really like this suggestion from Tony Nelson (small changes in name to traditional names):

    myemail = new CFMAIL( to='joe@email.com', from='bob@email.com', subject='hello', type='html') {
    Hi buddy,
    Just saying hi!
    }
    myemail.send();
    // or myemail.execute(); whichever.

    myemail = new CFMAIL();
    myemail.to = 'joe@email.com';
    myemail.from = 'bob@email.com';
    myemail.subject = 'hello';
    myemail.type = 'HTML';
    myemail.message = 'Hi buddy. ust saying hi!';
    // or myemail.body, I prefer body.
    myemail.CFMAILPARAM('c:\file.pdf');
    myemail.send();

    Both of these reoutes are clean and very readable. But a long HTML body would scramble the clarity and readability. I think the body must be in the brackets {} or in an attribute outside the function. Putting all of the parameters within the initial CFMAIL() parentheses is ugly. It will get very long and very difficult to check your matching opening/closing parentheses. Coders using editors that don't highlight matching parentheses would have a hell of time debugging. I think using {} curly brackets is much less ugly than really long parameters and values inside the initial function() parentheses.


    I second Patrick McElhaney's ideas (and others who expressed similar solutions) who support this:
    *************************************
    If you want to embed code in text, you could try the traditional route.

    cfmail(...) {
    I am text in the email!
    #setVariable(&quot;but&quot;, i_am(&quot;a&quot;,functionCall()))#;
    }
    *************************************

    I dislike the @body syntax.

    I think attributes/parameters should stay as such within the function() parentheses and any content wrapped in the body of a tag should be within the body of the {} curly brackets. I feel that is important, clear, readable, and straightforward.

    Those are my votes.

    Great discussion everyone.
  • 69 Rick O // May 19, 2009 at 9:00 AM

    Sean: I take your point about embedded logic tags, but take it one step bigger: What if the E4X literal is interpreted as a chunk of old-style code -- a sort of implicit version of this:

    &lt;/cfscript&gt; ... &lt;cfscript&gt;

    You've inverted the language, so that you are now embedding tags instead of embedding script. This would then work:

    // it's not just a literal,
    // it's a embedded chunk of code
    var q = &lt;cfquery ...&gt;
    SELECT *
    FROM myTable
    WHERE (col1 = &lt;cfqueryparam ...&gt;)
    &lt;cfif something&gt;AND (col2 = 1)&lt;/cfif&gt;
    &lt;/cfquery&gt;;

    If you're going to do it, you have to let me do clean (non-CF) XML E4X literals, too:

    // this creates an XML object,
    // not just a string with HTML in it
    var foo = &lt;em&gt;whatever&lt;/em&gt;;

    // this is just a string
    var flat = &quot;&lt;em&gt;whatever&lt;/em&gt;&quot;;
  • 70 Mark Jones // May 19, 2009 at 9:02 AM

    One comment on the project as a whole: The complication right now comes from a) trying to duplicate the functionality available to tags and b) being forced to keep the old script in place. I don't envy the committee this task; This is necessary, but it will likely still be rough around the edges and have a mashed-together feel. Especially if we add in some modernish syntax for the new stuff (mail / query objects) but retain the old methods (image functions).

    This probably isn't the time, but for the *next* CFML standard (and depending on the success of the initial attempt, I suppose), I'd love to see cfscript 2.0. Designed from the ground up as a brand new language, or at least a refresh. Use ECMAscript as the inspiration, build a consistent method for interacting with underlying systems (image, database, mail), and give the whole thing a more uniform, &quot;designed&quot; feel.

    Simultaneously, look at how tags and script work together. Try to make it as seamless as possible; A lot of us fear the &quot;two-language&quot; thing which, despite objections, is exactly what we're doing. Why not embrace it and work on melding the two approaches somehow. A much bigger project, certainly.
  • 71 Andy Sandefer // May 19, 2009 at 9:33 AM

    I often times like to put myself in a decision makers shoes and in order to do so I must understand their motivations. I also think that putting tags inside of the cfscript is just more lipstick on the pig. The tag syntax is not going anywhere so for all of you people like me who were drawn in by the simplistic beauty of that syntax please just relax!
    Come back to the heart of the issue and follow the copious amount of money that will be spent in making these features a reality - what's the motivation or Adobe, Railo or BD in doing this? I think that above all the motivation is to attract more java, .net and php developers. Sorry to hurt your collective feelings but this is largely not for us (the loyal cf'ers out there) because frankly they had us at hello and they've had many of us (and our clients) for a very long time. Sure we will benefit from this but ask yourselves (just as Adobe's product and marketing crews asked themselves before they went down this road) would you have continued on as a ColdFusion developer without this enhancement? I'm fairly certain that the answer for most of you is yes. If the point of this is to gain developers with backgrounds in competing technologies wouldn't you want to implement the most common, standards compliant methodology that your true target consumer is used to?
    Why are we truly being asked about this Sean? Why doesn't the committee go to a .net or php conference and ask those folks what it would take to get them to drop their proverbial hammers and go out to buy nail guns?
    I love CF and I'm not going anywhere. Most of the people who are reading this are rabidly coding in CF on a daily basis and they're not going anywhere either - whether cfscript grows ten heads or not.
  • 72 bill // May 19, 2009 at 9:45 AM

    A Groovy GString or similar Heredoc syntax would work for text normally parsed
    between tags. But, I'm not sure about the cfqueryparam syntax below ... Gant (http://gant.codehaus.org/) has addressed some related issues - Gant wraps Groovy around Ant.



    public function runQuery(){
    cfquery(name='q',datasource='test'){
    '''
    select foobar
    from foo
    where bar = #cfqueryparam(cfsqltype=&quot;cf_sql_varchar&quot; maxlength=&quot;12&quot; value=&quot;#variables.fu#&quot;){}#
    '''
    }
    return q;
    }

    bill
  • 73 Rick O // May 19, 2009 at 9:59 AM

    Blarg. I've posted a clearer, non-mangled example of my idea here:

    http://rickosborne.org/blog/index.php/2009/05/19/cf9-e4x-c4x/
  • 74 Gadi // May 19, 2009 at 10:08 AM

    @Sean, I think if the point is to lower to barrier of entry for other languages, you should consider object syntax much more heavily.

    While it would be much more verbose, you still have tag syntax to fall back on. Again, if you are trying to make it easier for .net or java or even php developers to pick it up, I think you have to go to object syntax.
  • 75 Peter J. Farrell // May 19, 2009 at 10:08 AM

    @ALL, well I love to hear about all your dreams about CFSCRIPT, I think it would be better to try to keep comments to the point of what was outlined in Sean's blog post body. As the newest member of the committee, I have the disadvantage to coming into this &quot;late in the game.&quot; I know we'll have more discussions on other things in CFSCRIPT in the near future so don't think that if you don't get everything and the kitchen sink as suggestions on this post. Not trying to quell the great discussion here, but honestly just trying to keep my head from spinning.

    @Mark, thanks for pointing out that the committee doesn't have an easy job. I think it's easy for most people to forget about backward compatibility (BC) and I'm glad that you pointed out that we have a partial implementation already and it's something we can't change unless we want to break code.

    @Mike, unnecessary or not - CFSCRIPT is coming in some form or another. If the committee doesn't provide a standard, each CFML engine will implement bits and pieces differently. Ultimately, that would do more harm to CFML as a language than for us to provide a standard so that all engines can implement.

    @AdamCameron, I think your point about backward compatibility getting in the way of forward movement is flawed. I'm sorry if you take offense to that, but there is too much code out there that *will* break and breaking BC does not help people in which we break their code -- they won't make sure of any of the new features with broken code! I came after the votes on writeDump() and writeLog() but I agree with votes on those constructs as they are no different than &lt;CFOUTPUT&gt; becoming writeOutput (as it already is implemented).

    @Justin, thanks for brining up custom tags. I just brought up this question on the committee mail list yesterday. We want to support it, but at the moment according to Sean &quot;we're having problems reaching consensus.&quot; I think it's because we need to get some of the bigger issues like cfmail and cfquery in CFSCRIPT out of the way first. More than likely, custom tags will follow similar constructs because custom tags have a inner body -- just like cfmail and cfquery. Yes, this is on the list to do -- I'll do my best to make sure this is *not* forgotten by the committee.
  • 76 John Farrar // May 19, 2009 at 10:18 AM

    @Mark,

    This cfscript 2.0 concept is something you have my vote on also. IMO the need to hold things in version one compliance is a bear! It would just take an attribute called &quot;version&quot; to resolve that issue. This would solve a number of issues.
  • 77 Adam Ness // May 19, 2009 at 11:35 AM

    @radekg I think you should do a little more investigation into MXML, XAML, LINQ, and FXScript. These languages are declaritive syntaxes for an imperative language (ActionScript, C#, VB.Net, Java ). These syntaxes for imperative languages are used for several purposes, including Visual Layout, Database Access, Event Dispatching, and Dependency Injection. My original point stands, many languages that were established with strictly imperative syntaxes, are now moving towards using declarative syntaxes inline or with another language where they are appropriate. Before LINQ was introduced, C# and VB.Net didn't have a declarative Database access construct. Before MXML was introduced, ActionScript did not have a declarative Object Inheritance and Composition construct. Before FXScript was released, Java didn't have a declarative way to lay out graphics on a page. Yes, they are ultimately compiled to the same form that the language they are extending, but they're recognizing that there are some times when a object/function call syntax is harder to write and read than a nice declarative syntax.

    Conversely, cfscript is an imperative syntax for CFML, which grew up largely as a declarative language, with a few imperative constructs.

    @Mike Kelp brings up a lot of really good points in trying to keep the language as simple as possible. Adding a

    tag { &lt;cfldap ..... /&gt; }

    construct adds complexity to the syntax. Adding a

    mail( from = &quot;foo@mail.com, to=&quot;bar@mail.com&quot; ) {

    mailpart( type=&quot;text/html&quot; ) { &quot;&lt;h1&gt;MAIL HERE!&lt;/h1&gt;&quot;} ,

    mailpart( type=&quot;text/plain&quot; ) { &quot;MAIL HERE!&quot; }

    };

    construct is even more complex, and hard to read (and doesn't really buy anything over tag-based anyhow). Just look back through the comments to see examples of how hard it is to read the code that various folks have typed. The least new language constructs are introduced with a straight OO format:

    var query = new Query( &quot;myDSN&quot; );
    query.setSQL(&quot;SELECT * FROM myTable WHERE i=?&quot;);
    query.setQueryParam(1,i,CF_SQL_INTEGER);
    var data = query.execute();
    var results = query.getResults();

    But if I'm going to do that, why wouldn't I just write the whole thing as a groovy servlet, where I can save myself the semi-colons and braces? What does ColdFusion buy me if I'm working with raw objects?
  • 78 Adam Ness // May 19, 2009 at 11:52 AM

    @rick o I like your example a lot... Very cool. I hadn't considered full e4x support, but your example really illustrates how much of a boon that could be to the language. XML is already easier in ColdFusion than most other languages, but adding e4x support like you describe would be immensely powerful, and solves the question of how to implement the &lt;cfxml&gt; tag in CFScript right off the bat!

    @Peter J Farrell I definitely agree with you that backwards compatibility is a huge concern, and should be kept in mind by everyone involved. Glad to have you on the team working on that and the Custom Tag bit.

    @John Farrar A &quot;version&quot; attribute works well for &lt;cfscript version=...&gt; blocks, but it becomes more complicated with the &quot;Extended Core 2009&quot; that Sean was talking about. I suppose that you could specify that anything without a &lt;cfscript&gt; block would implicitly be version 2.0, but that doesn't leave much room for future expansion.

    I suppose one way of handling this might be to introduce &quot;Attributes&quot; a la Java/ActionScript/C#, so the .cfc would look like:

    [version=2.0]
    import mxunit.framework.*;

    component extends=&quot;Foo&quot; {
    ...
    }
  • 79 Charlie // May 19, 2009 at 12:14 PM

    I agree with the others who've mentioned that to decide which route to take, you have to decide what goal you want to accomplish.

    Do you want the most beautiful looking query? Then a heredoc or similar is the answer. But where's the conditional processing or variable assignments, etc.? I think that's the problem that Sean started the thread off with.

    Do you want to make CF more inviting to .NET or Java developers? Then go objects all the way. It's ugly, but it's functional. (...wait, I meant... it works fine! :) )

    Or maybe somewhere in the middle, where it still contains all the functionality of the language (and original &lt;cfquery&gt;), but is a little less ugly than object syntax and string concatenation, and maybe more familiar looking to CF developers?

    Use an explicit writeSql() (or something like that) to output your sql statements within the query's body, and you can then use all your other language functions and conditionals to your heart's content. It works almost exactly the same as &lt;cfquery&gt;, but in function form, and with the addition of the writeSql() wrapper.

    It is almost as verbose as string concatenation, but it's more straightforward about what's going on, and it would make the implementation and explanation of QueryParam a whole lot simpler: It must be in a writeSql() statement, which must itself be in a query() block.

    query(datasource=&quot;DSN&quot;, name=&quot;MyQuery&quot;) {
    writeSql(&quot;SELECT * FROM Table&quot;);
    writeSql(&quot;WHERE Column LIKE #QueryParam(value='#MyValue#%', sqltype='cf_sql_varchar')#&quot;);
    for(i=1;i&lt;10;i++) {
    writeSql(&quot;OR Column2 = '#i#'&quot;);
    }
    writeSql(&quot;ORDER BY Column ASC&quot;);
    }

    I posted a similar code sample earlier that got mangled, so here's another version in case this one gets mangled, too:

    http://www.charliecochran.com/cfscript.html
  • 80 TJ Downes // May 19, 2009 at 12:44 PM

    I also agree with the cfscript versioning, as Mark and John F. have mentioned.
  • 81 Scott G. // May 19, 2009 at 2:24 PM

    I don't think Queries as objects is wrong:

    myQuery = Query();
    myQuery.datasource = &quot;dsn&quot;;
    myQuery.setStatement(&quot;select * from table where active = ? order by ?&quot;);
    myQuery.setParameter(1, &quot;true&quot;);
    myQuery.setParameter(2, &quot;first_name&quot;);
    myQuery.execute();

    It follows generally accepted programming practices in most modern languages, and the only downside is that more code may be necessary as opposed to the tag version. Even still, it's cleaner than most alternatives already suggested (aside from objects, that is.

    If there's a strong aversion to that for whatever reason, maybe a syntax kind of like this would work - passing arguments to the query as part of the method call:

    Query(
    name = &quot;myQuery&quot;,
    datasource = &quot;dsn&quot;,
    timeout = &quot;120&quot;,
    maxRows = &quot;10&quot;,
    query = &quot;select * from table where active = ? order by ?&quot;,
    queryParameter(cfsqltype=&quot;cf_sql_boolean&quot;, value=&quot;true&quot;, null=&quot;false&quot;),
    queryParameter(cfsqltype=&quot;cf_sql_varchar&quot;, value=&quot;first_name&quot;, null=&quot;false&quot;),
    ...queryParameter());

    This would make sense, while not using the query as an object. It would also allow you to dynamically create the query itself, since you would be able to pass a string as the query parameter. The only hurdle to this is allowing an arbitrary number of parameters to be passed to the Query() function. Similar things have been done in other languages like C# (console.writeline(), for example)

    ------------

    cfsavecontent could be done like this:

    variableName = saveContent{
    for (i = 1; i lte 10; i = i + 1) {
    writeoutput(&quot;The value of i is &quot; &amp; i);
    }
    }

    This methodology would allow you to nest code within, and would work in a similar manner to the try{} catch{} in the original post. In addition, you could also use this for cftransaction and other tags.

    ------------

    cfmail could also be accomplished like my Query example:

    Mail(
    to = &quot;your@mother.com&quot;,
    from = &quot;her@son.com&quot;,
    subject = &quot;Hi Mom!&quot;,
    body = &quot;This would be a plaintext body&quot;
    );

    Or, alternately, if you wanted to do multipart email:

    Mail (
    to = &quot;your@mother.com&quot;,
    from = &quot;her@son.com&quot;,
    subject = &quot;Hi Mom!&quot;,
    mailPart(type = &quot;text/plain&quot; body = &quot;This is a plaintext mail body&quot;, charset=&quot;utf-8&quot;),
    mailPart(type = &quot;text/html&quot; body = &quot;&lt;html&gt;&lt;body&gt;This is an HTML mail body&lt;/body&gt;&lt;/html&gt;&quot;)
    );

    ------------

    I don't like the use of write[anything] - writeOutput was awkward at first, because it didn't jive with the rest of the language - I think perpetuating that with writeLog() and writeDump() would be a disappointment.

    A version tag isn't a terrible idea, but I'm not convinced it's necessary.

    I think tags within scripting, as proposed, would be a bad idea.
  • 82 Adam Ness // May 19, 2009 at 2:26 PM

    @Sean - I wouldn't call python or groovy completely typeless. They have classes and inheritance, they're just not strict about what type of variable functions accept or return. They've got structure and types while being flexible about what types can be used where.

    Javascript on the other hand, has only 1 type: Function/Object/Structure/Array. &quot;new&quot; is just a shortcut for calling the function and retrieving a reference to the function's &quot;scope&quot;. [] is a shortcut for creating a new object, mixing in the Array methods, and adding some values to it. {} is a shortcut for creating a raw object. {}.prototype is a shortcut to adding things to the function's scope without rewriting the function. It's a real brain-bender, and something I definitely don't think should be emulated in CFScript.
  • 83 Aaron Neff // May 19, 2009 at 2:49 PM

    +1 for cfscript versioning
  • 84 Sean Corfield // May 19, 2009 at 3:10 PM

    @Adam, I never said they were &quot;completely typeless&quot;. I said the power comes from their &quot;typeless nature&quot;, i.e., the ability to completely drop type checking when you need to. Yes, you can write strictly typed Groovy code - almost no one does. If you want that strict typing, you use Java instead.
  • 85 Justin Carter // May 19, 2009 at 3:48 PM

    @Peter J Farrell: Good to know custom tags have already been considered :)

    The more I look at it, the more correct the E4X style syntax is; look at Rick's blog post that he linked to above. Not only is it a simple way to solve the issues with tag bodies and nested tags (i.e the cfmail, cfquery, etc), it will work for custom tags and it could enable us to write XML literals (or even chunks of HTML) without parsing strings / wrapping things in quotes. As long as there is a matching pair of opening and closing tags it's fair game to treat as code that CF could already parse (the extra XML detection smarts would need to be added though for that one case, and a non-XML compliant chunk could be assumed HTML and treated as a string - unless someone wants to add &quot;cfdom/node&quot; type support too :) hah).

    I think trying to solve this in a &quot;script only&quot; kind of way could lead to even uglier syntax or lack of flexibility in the language (as shown by most of the attempted suggestions), while the E4X way of doing things is already out there and already recognised, and would have no learning curve because the tags are the same as we have always used.
  • 86 Steve 'Cutter' Blades // May 19, 2009 at 5:39 PM

    @anthony -

    Yep, I be confuzed:p

    I meant that an ECMAScript presentation makes more sense. It falls in line with other Adobe offerings (as3), and builds upon other core web development competencies in practice (JavaScript/ECMAScript).
  • 87 Ryan Cogswell // May 19, 2009 at 8:07 PM

    Regarding cfmail in cfscript:
    I think it is desirable for the overall code structure to be able to remain essentially the same when moving code back and forth between tags and script. Though I might be replacing tags with functions and introducing curly brackets in place of begin/end tags, I want to be able to move the structure of conditions, loops, and setting variables from tags to script without needing to significantly refactor the code. Thus I am not in favor of handling the message body as a function parameter (at least not as the only way of doing the body), rather I would be in favor of something more like the following:

    &lt;!--- tag example ---&gt;
    &lt;cfmail from=...&gt;
    &lt;cfif moreThanOneSurveyToComplete&gt;
    You need to complete evaluations of the following people:
    &lt;cfloop ...&gt;
    #personNameArray[personIndex]#
    &lt;/cfloop&gt;
    &lt;cfelse&gt;
    You need to complete an evaluation of #personNameArray[1]#.
    &lt;/cfif&gt;
    &lt;cfmailparam file=&quot;#evalFormFileName#&quot;&gt;
    &lt;/cfmail&gt;

    /* transferred to script */
    cfmail(from=...) {
    if (moreThanOneSurveyToComplete) {
    writeToMailBody(&quot;You need to complete evaluations of the following people:&quot;);
    for (...) {
    writeToMailBody(&quot;#personNameArray[personIndex]#&quot;);
    }
    } else {
    writeToMailBody(&quot;You need to complete an evaluation of #personNameArray[1]#.&quot;);
    }
    cfmailparam(file=&quot;#evalFormFileName#&quot;);
    }
  • 88 Jim Pickering // May 19, 2009 at 9:34 PM

    While it is a creative and valid idea for a solution, I do not like the e4x syntax idea. It totally breaks the consistency of CFScript by returning to a tag-based syntax which is the reason we use CFScript; to get away from the tags. I understand ColdFusion is about the tags, but CFScript is like an efficiency shortcut in ColdFusion that the e4x idea breaks.

    I am onboard with the suggestions from @Tony Nelson. So that would be cfquery and cfmail as objects. I'd like for Sean to comment on Tony's question: Just curious, but why are people suggesting using cfmail(@body='') instead of just cfmail(body=''). If you forget about how the tag currently works, is there a reason why the body attribute would be considered different from the rest of the attributes?

    And finally, I would like to see some feedback from anybody on @Ben Pate's suggestion of a *.cfs file extension. I like this idea a lot.
  • 89 Justin Carter // May 20, 2009 at 1:59 AM

    @Jim Pickering: The thing is that the E4X-style statements are a simple, consistent solution. The script alternatives for handling tag bodies and custom tags need to be consistent as well, otherwise you end up with weird, hard to remember syntaxes for different functions and services, and currently no solution for custom tags at all. Plus if you compare some of the examples above, the E4X-style syntax alternative is actually more concise :)
  • 90 Marko Simic // May 20, 2009 at 4:50 AM

    @Mike Kelp
    I think that idea behind CFSCRIPT is to make transition from script to tag-based development easer.

    @David Hammond
    I am &quot;fighting&quot; with the same problem in my company. But, on the other hand, knowing CF means knowing both: cfscript and cftags.
    TBH this is just a minor problem among other problems we have :))

    @Committee
    What about replacing CFSAVEVONTENT inside CFSCRIPT with special markings like [@CFSAVEVONTENT varname=&quot;varcont&quot;] and ends with [@CFSAVEVONTENT].
    Everything that writeOutputs between markings will be stored in &quot;varcont&quot; variable.

    Whatever solution you adopt, do not reinvent the wheel.
    Stick to syntax and semantic of most-popular OO languages.

    Good luck
  • 91 Matthew Lesko // May 20, 2009 at 6:27 AM

    @Sean &amp; @Adam Ness: a little off topic, but to second Adam's comment, I think the ability to define an object in ColdFusion (CFML or CFscript) that can be called in Java would be a &quot;very useful thing.&quot;
  • 92 Clint Willard // May 20, 2009 at 6:30 AM

    var mailBody = &quot;My name is &quot; + allCaps(getUser(userID).getName()) + &quot;.&quot;;
    mailResults = cfmail(){ mailBody }
    or better
    mailResults = cfmail(body=mailBody);

    I'm perfectly used to having to parameratize mixing of string and code, why change now? Do you really need to be able to place inline text+code within a mail function? Then:

    cfmail(){
    &quot;My name is &quot; + allCaps(getUser(userID).getName()) + &quot;.&quot;
    }

    Being an OO person I ca also accept cfmail as an object.

    myPostOffice = new cfmail();
    myPostOffice.setBody(myMessage);
    myPostOffice.send();
  • 93 Mark Jones // May 20, 2009 at 6:32 AM

    The more I think about it, the more suggestions like Ryan's example above make sense for merging into existing cfscript. I still like objects, but it feels a little tacked onto current cfscript. E4X or similar opens too many questions and, while I'd love to see this contemplated for the future, now is probably not the time. (as a note, there are some things that tags are *more* efficient at than script, hence the suggestions and this whole discussion)

    Some sort of bracket/enclosure/heredoc is the best analogue to how the tags work, and thus is probably the best option. Simple {} is probably not enough, though. It's too similar-looking to other constructs and it forces us to escape } characters in the content. The last issue is that using *functions* within the &quot;body&quot; feels... odd.

    mail(to=...,from=...){{

    #mailparam(...)#

    #mailpart(type=&quot;text/html&quot;){{ ... }}#

    #mailpart(type=&quot;text/plain&quot;){{ ... }}#

    }}

    ...Especially since it'll open more questions as to whether #s are needed or not. I would assume the &quot;functions&quot; above would, since they are not normal content... But this throws us out of a &quot;script&quot; context into something that looks more like the content of a normal &lt;cfoutput&gt; block.
  • 94 John Hodorowicz // May 20, 2009 at 8:21 AM

    I prefer the object syntax; more readable and promotes best practices. I think Ryan Heldt's function call is fine too.

    As long as I can still build a struct with the values and pass it as an argument collection then I'll be fine with whatever implementation.
  • 95 Dan Roberts // May 20, 2009 at 9:17 AM

    I am a bit late to the game and admittedly have not read through every comment above.

    I have also adjusted my code to try to make it readable in the comments but not sure if it will work. I am using double breaks and &quot;_ &quot; in place of tabs.

    It feels like there needs to be a new syntax or for building up output while also making other features of the language available. When using this, any output would go to the local output instance, not the browser output. A block elenent named something like &quot;captureoutput&quot;.

    With some syntactial sugar the usage of &quot;writeOutput&quot; and &quot;captureOutput&quot; could be reduced to syntax.

    MAIL

    // create mail object

    email = new mail(type=&quot;html&quot;,from=?,to=?, etc);



    // add attachmentss

    for( filename in attachements);

    _ email.addAttachment(filename);



    // create and send each unique message

    for( contacts in qContacts){

    _ email.body = captureoutput{

    _ _ //create mail body

    _ _ writeOutput(&quot;

    _ _ _ &lt;p&gt;This is the message of email. The attachments to this message should be as follows:&lt;/p&gt;

    _ _ _ &lt;ul&gt;

    _ _ &quot;);

    _ _

    _ _ // this could be a variable output instead of dynamically done per contact

    _ _ for(filename in attachments){

    _ _ _ writeOutput(&quot;

    _ _ _ _ &lt;li&gt;#attachments[filename]#&lt;/li&gt;

    _ _ _ &quot;);

    _ _ }

    _ _ writeOutput(&quot;&lt;/ul&gt;&quot;);

    _ };



    _ // send each version of the message

    _ email.send();

    };



    QUERIES



    For queries the same could be true but also the queryparam elements could output a unique ID into the SQL statement



    // create query object

    contacts = new query(datasource=&quot;customers&quot;);



    // build up SQL while also adding query parameters

    contacts.sqlstatement = captureoutput{

    _ writeOutput(&quot;

    _ _ SELECT ContactID, Name, Email

    _ _ FROM Contacts

    _ _ WHERE AccountID = #contacts.addqueryparam( arguments.accountid, &quot;sqltype&quot;, etc )#;

    _ &quot;);

    };



    contacts.execute();



    The SQL statement that is built up would have a specific sequence that links the area that the queryparam was inserted to the actually queryparam object.



    SELECT Name, Email

    FROM Contacts

    WHERE AccountID = {{qp:5EC2A454-1143-E453-8C55EA876A3447DF}}



    Doing this would even allow you to dynamically change queryparameters after the creation of the SQL statement by keeping the ID intact instead of changing the query statement or just adjusting the parameter object.



    // create query object

    contactPets = new query(datasource=&quot;customers&quot;);



    qpContactID = new queryparam( &quot;&quot;, &quot;sqltype&quot;, etc);



    // build up SQL while also adding query parameter

    contactPet.sqlstatement = captureoutput{

    _ writeOutput(&quot;

    _ _ SELECT Name, Species

    _ _ FROM ContactPets

    _ _ WHERE ContactID = #contacts.addqueryparam( qpContactID );

    _ &quot;);

    };



    // now actually use the query object for each contact but adjust the queryparameter dynamically

    for(contact in contacts){

    _ qpContactID.setValue(contacts.contactID);

    _ contactPet = contactPet.execute();

    _ writeOutput(&quot;

    _ _ &lt;li&gt;contact: #contact.name# pet: contactpet: #contactPet.name# (#contactPet.species#)

    _ &quot;)

    }
  • 96 Scott G. // May 20, 2009 at 1:03 PM

    I agree with Ryan Cogswell's suggestions for CFMail and CFQuery... these fit in line with other syntax that are already being used for cfscript.

    Anything that's a tag can be converted into cfscript easily this way, This would also entirely take care of the existing issues you're trying to solve for cfquery, cfmail and cfsavecontent.

    query(attribute1=value1,...attributen=valuen) {[same as the body of cfquery]}

    mail(attribute1=value1,...attributen=valuen) {[same as the body of cfmail]}

    saveContent(attribute1=value1,...attributen=valuen) {[same as the body of cfsavecontent]}

    cftransaction() {
    insertQuery();
    }

    It's simple, concise and already jives with the other cfscript syntax - it mimics existing for/while loops, and is also in line with the new try/catch blocks being proposed.
  • 97 Adam Ness // May 20, 2009 at 6:44 PM

    Thinking about things a little more, if the e4x solution is deemed &quot;unusable&quot; for whatever reason, a mildly good intermediary might be:

    query(dsn=&quot;foo&quot;,name=&quot;bar&quot;)[
    &quot;SELECT * FROM baz WHERE zot=&quot;,
    queryParam(value=yaz,cf_sql_type=&quot;CF_SQL_VARCHAR&quot;),
    &quot;AND sim=&quot;,
    queryParam( value=salabim,cf_sql_type=&quot;CF_SQL_VARCHAR&quot;)
    ];

    I prefer the []'s instead of the {}'s because it makes it apparent that what you're adding to the &quot;tag&quot; is an array of sub-elements, where order matters. {}'s when not applied to function bodies imply that order doesn't matter (such as when specifying the fields and methods in a CFC, or when specifying a structure).

    One question I have about this whole discussion though, historically, all of the functions could be called using CFSet as well as within cfscript blocks. Would the same hold true of this syntax?

    i.e. Could I type: &lt;cfset mail(from=&quot;foo&quot;,to=&quot;bar@mail.com&quot;,subject=&quot;Some test&quot;)[mailpart(type=&quot;text/plain&quot;)[&quot;The quick brown fox jumped over the lazy dog&quot;],mailpart(type=&quot;text/html&quot;)[&quot;&lt;h1&gt;The quick brown fox jumped over the lazy dog&quot;]] /&gt;
  • 98 Sean Corfield // May 20, 2009 at 6:55 PM

    @Scott, but you *can't* just have the body behave the same way for mail / query / savecontent. In tag syntax, the body can be a mix of tags - code - and plain text. In script syntax, you cannot easily tell code from plain text. Ryan's suggestion was essentially to require writeOutput('string'); for anything that would have been plain text. It's definitely a possibility but it seems verbose and ugly:

    mail( from=&quot;foo&quot;, to=&quot;bar@mail.com&quot;, subject=&quot;Some test&quot; ) {

    mailpart( type=&quot;text/plain&quot; ) {

    writeOutput( &quot;The quick brown fox jumped over the lazy dog\n&quot; );

    }

    mailpart( type=&quot;text/html&quot; ) {

    writeOutput( &quot;&lt;h1&gt;The quick brown fox jumped over the lazy dog&lt;/h1&gt;&quot; );

    }

    }

    Note that you'd need to specify newlines where you wanted them as well.

    Think of how that looks for a 50-line email or query...
  • 99 anthony // May 20, 2009 at 7:34 PM

    I find that putting the mail, savecontent and query body between the curly braces is way too confusing. If I knew nothing about CFScript and looked at it, my PHP and Java experience would lead me to think it was a function declaration.
  • 100 matt j // May 20, 2009 at 7:35 PM

    I would like to add a +1 for:

    tag { ... }
    ternary operators
    rick o's example
    and closures

    and what if cf/processingdirective had an attribute such as syntax=&quot;cfml|cfscript&quot; the default being cfml that could state that the page was to be processed as cfscript or cftags? This seems to fit within the whole intent of that tag (tell coldfusion how to process the page)

    so
    &lt;cfprocessingdirective syntax=&quot;cfml&quot;/&gt;--or without this at all
    code tha page just like we do today

    or

    processingDirective(syntax='cfscript');
    omit the need for script tags but makes a valid case for tag { ... } or something like it to inject tags into an otherwise scripted page
  • 101 Ryan Cogswell // May 20, 2009 at 7:45 PM

    Just to clarify my earlier post -- I'm all for coming up with some sort of syntax for creating multi-line strings in some more convenient fashion where you don't need to escape quotes or do explicit newlines; but even though it would be an extremely useful feature to use for creating a mail message body or a query string, it seems like it would be cleanest to look at these as independent problems.

    Problem 1: Come up with an approach to convert to script those tags that have an inner body which may contain control constructs. My suggestion is to be able to append strings to the inner body incrementally (via a function call) in order to still allow for control constructs to be interspersed around those strings and to keep the overall flow as similar to cfml as possible.

    Problem 2: Come up with an approach to conveniently create multi-line strings. I am not familiar with the various &quot;standard&quot; approaches for doing this in other languages, so I don't have a strong opinion on the particular syntax. I suspect that the syntax for this can be much simpler/cleaner if we do NOT try to allow control constructs within the multi-line strings -- i.e. limit the strings to what you can do within a regular quoted string (variables and function calls within pounds) but allow newlines and quotes. Then the only problem to solve is the syntax for beginning and ending the string. I do not think we should use three quotes for this purpose since in CF that is how you would begin a string that starts with a quote and thus this would have backwards-compatibility issues (e.g. &lt;cfset myString = &quot;&quot;&quot;This string should be displayed with a quote at the beginning and end because cf escapes quotes by duplicating them.&quot;&quot;&quot;&gt;).
  • 102 Sean Corfield // May 20, 2009 at 8:39 PM

    @Ryan, good point on the compatibility of using triple quotes (which is the standard in some other languages like Groovy).

    As folks can see from this long thread, language design can be very, very hard at times!
  • 103 Ciaran Archer // May 21, 2009 at 6:33 AM

    I would go for the solution as described by Steve 'Cutter' Blades. This sort of object notation syntax is used a lot in Javascript and it should lend itself to cf structures pretty well.

    var someResult = new cfmail({ to: sendTo, from: sentFrom, body: 'This is my body', cfmailparam:[{ name: 'prm1', value: 'first value' },{ name: 'prm2', value: 'second value' }] });
  • 104 Ryan Cogswell // May 21, 2009 at 6:54 AM

    Perhaps a CF-ized version of the triple quotes might be quote-pound-quote:

    &lt;cfset &quot;#&quot;Here's

    my

    multi-line

    string&quot;#&quot;&gt;

    I believe that combination would always be considered a syntax error today which would make it a good candidate from a backwards-compatibility standpoint.
  • 105 Scott G. // May 21, 2009 at 7:29 AM

    @Sean: Yes, you're right - you can't just have straight text in the body of the query/mail/savecontent, I agree. I see that my comment was a little unclear - I was just trying to truncate the code to fit within the confines of your commenting system.

    A fundamental shift in thinking would be to allow quotations to essentially act as writeoutput does when they're not within the {}'s of a function and within the {}'s of a method - this would fix that issue, but I don't think it's necessarily the proper solution because it's a huge shift in thought and existing syntax, albeit much cleaner than the E4X that's being proposed ;-)

    @anthony: Your if, for and while statements in PHP and Java don't have curly braces around them?
  • 106 tony petruzzi // May 21, 2009 at 7:38 AM

    whatever you do, please consider and fight for starting all the new tag specific functions to start with cf, as in use cfmail() instead of mail(). my main concern is that most people that i know that are doing their own ports of tags to cfscript are using dump() instead of cfdump(). by the new cfscript functions not starting with cf, it will cause problems with a lot of already existing applications and make upgrading to cf9 impossible.

    to be honest i would actually love for this to be an application setting we could set in the application.cfc like: this.CFScriptTagSyntax = 'cf'.

    also it will be easier for people just getting their feet wet with the new syntax to follow along with a tag based comparison.
  • 107 Sean Corfield // May 21, 2009 at 8:24 AM

    @Ryan, that code doesn't throw an error but it does have a surprising result. Try it :)

    @Scott, we considered changing how string literals behave inside tag bodies but it was very confusing and produced some subtle strange situations.

    @tony, one of our current discussions is focusing on exactly that issue: cftagname vs tagname. There are pros and cons on both sides, unfortunately. Your suggestion of an application setting wouldn't work tho' because compiled CFML code can be executed by multiple applications.
  • 108 Dan Roberts // May 21, 2009 at 8:38 AM

    @Sean, Ryan mentioned it but I'm curious about you thoughts on this. Do you think it is important to allow output and processing to occur with-in the same block of code? I think this is something that has been really useful in CF that could (should?) be carried over to script in some way. Do you feel it is important?

    I am of the mind that everything should be possible with-in regular syntax and setting object properties. However I think it would be great to have a new syntax that can capture output, allow all processing capabilities, and be nested in a function parameter.

    Since greater than and less than signs aren't being used then maybe they could be leveraged. Maybe a &quot;captureOutput&quot; block could be defined by &quot;&lt;&lt;&quot; and &quot;&gt;&gt;&quot; and output blocks could be surrounded by &quot;&lt;#&lt;&quot; &quot;&gt;#&gt;&quot; instead of a function.

    object.setSomeProperty(&lt;&lt;

    &lt;p&gt;Text to be output but #this# would not be evaluated&lt;/p&gt;

    _ &lt;#&lt;

    _ _ &lt;p&gt;More text ouptut but #this# is evalutated&lt;/p&gt;

    _ &gt;#&gt;

    &gt;&gt;);
  • 109 John Hodorowicz // May 21, 2009 at 8:55 AM

    I'd argue against adding new functions for cfscript starting with &quot;cf&quot;. There are no other functions in cfscript starting with &quot;cf&quot; so lets stay consistent.

    If the new cfscript allows function overloading there shouldn't be an issue with already defined user functions. If not, I dont think doing a find and replace would be difficult if one wants to upgrade to cf9. Cfscript versioning could help users keep their current user defined functions until they're ready to utilize cf9 scripting.
  • 110 Ben Pate // May 21, 2009 at 9:00 AM

    @Sean: Yes, this is clearly a very difficult balancing act. Others have already said it, but THANK YOU for tackling hard problems like this. At some level, it's fun to sit back and watch so many very smart people come up with so many fundamentally opposed solutions.

    What I love (+1)
    ----------------
    As CF has grown, the general approach has been to add new functions directly to the top level namespace. This is easy, but we're quickly inheriting a very overgrown language. If we're making fundamental improvements to CFSCRIPT, then let's try to enhance it in a way that's sustainable for the long term.

    I really like the OO approach that's been floated about:

    m= new ColdFusion.mail(to=&quot;&quot; from=&quot;&quot;);
    m.addAttachment(x);
    m.setBody(&quot;&quot;);

    I think this works well me because then the language can define a number of high-level resources under one protected namespace, and then we don't have to clutter the language with tons of new stuff. Objects in this namespace would enhance the entire platform, and not be isolated solely to CFSCRIPT. Perhaps we could even use this approach down the road to clear up the image*() functions that everyone loves so much :).

    If the OO/namespace idea does get &quot;voted off the island&quot; then I'd still like to give a +1 to the &quot;JSON-style&quot; notation, such as:

    cfmail({to=&quot;&quot;, from=&quot;&quot;, attachment=[&quot;&quot;, &quot;&quot;]});

    This syntax matches what we're doing with Javascript/AJAX toolkits, so it's one less context-shift to have to manage.

    What I hate (-10)
    -----------------
    The proposals for adding &lt;tags&gt; directly into script are elegant, but I think it would be too confusing for everyone involved. The CFEclipse plugin has a hard enough time parsing my files as it is. And I feel the sam about the &quot;tag() {body}&quot; suggestions.

    I fear that these solutions would be elegant, but are a big departure from the keep-it-simple philosophy that has made CFML so great. I don't see how this would be easy to explain to a new developer

    What I don't understand
    -----------------------
    Last (sorry for the long post). I don't understand the need to add &lt;CFSAVECONTENT&gt; into cfscript. Why do we need this at all? Here's a solution that works today:

    &lt;cfscript&gt;
    y=&quot;
    All we are
    is dust in the wind,
    dude
    &quot;;
    &lt;/cfscript&gt;


    Thanks to everyone who's contributing to make CFML better in the future!
  • 111 Sean Corfield // May 21, 2009 at 9:06 AM

    @Dan, you ask: &quot;Do you think it is important to allow output and processing to occur with-in the same block of code? I think this is something that has been really useful in CF that could (should?) be carried over to script in some way. Do you feel it is important?&quot;

    Yes, that's why this problem is so hard to solve, unfortunately. If we are prepared to give that up, we could just force people to concatenate strings and pass those to mail() as body= or query() as sql= and ignore savecontent() altogether.
  • 112 Charlie // May 21, 2009 at 9:07 AM

    &quot;Think of how that looks for a 50-line email or query... &quot;

    @Sean: But it wouldn't need to look that bad, because there's no reason you can't put multiple lines of a query or email into a single writeOutput(). In fact, for most queries there would be only one writeOutput() required.

    query(datasource=&quot;DSN&quot;, name=&quot;myQuery&quot;) {

    writeOutput(&quot;

    SELECT FirstName, LastName, DateOfBirth

    FROM Employees

    WHERE LastName LIKE #QueryParam(value='#Form.Search#%', sqltype='cf_sql_varchar')#

    ORDER BY LastName ASC, FirstName ASC

    &quot;)

    }
  • 113 Dan Roberts // May 21, 2009 at 9:25 AM

    I think the most powerful thing to do would be to add features to the language that could be used in any context. Instead of giving special functions/objects a body with {} that map to some random property, provide an easy way to capture a body into any context.

    As I was stating before, some sort of capture output directive like &lt;&lt; and &gt;&gt; that could be in the context of a parameter or variable assignment would allow for a wide range of possibilities.

    new mail(from=&quot;me@mine.com&quot;, to=&quot;you@yours.com&quot;, text=&lt;&lt;

    _ perform some processing

    - output some plain-text content

    &gt;&gt;,

    html=&lt;&lt;

    _ perform some processing

    - output some html content

    &gt;&gt;);

    // if there is only one parameter to a function then this could be done

    mail.setText(&lt;&lt;

    _ processing and output

    &gt;&gt;);

    // you can also save to a variable which would be an alternative to &quot;savecontent&quot; and even make it better by allowing for concatenation just based on type of assignment

    variable &amp;= &lt;&lt;

    _ processing and output

    &gt;&gt;
  • 114 Adam Ness // May 21, 2009 at 9:57 AM

    @John Hodorowicz's reply brought up another good point about the ideas for cfscript versioning: What &quot;Version&quot; of cfscript is used in cfset statements, or in #...# blocks? If you just turn &lt;cfmail&gt; into mail, and separate them by versioning script blocks, then you have a very odd situation like this:

    &lt;cfset mail(&quot;someone.else@somewhere&quot;, &quot;adam.ness@gmail.com&quot;,REMINDER_EMAIL) /&gt;
    &lt;!--- Calls my existing &quot;mail&quot; udf, accepts arguments to : String and from : String ---&gt;

    &lt;cfscript version=&quot;2.0&quot;&gt;
    mail( from=&quot;someone.else@somewhere.com, to=&quot;adam.ness@gmail.com&quot; ){.....};
    // Calls the new CFScript mail function
    &lt;/cfscript&gt;

    There are other more subtle issues too.
  • 115 John Hodorowicz // May 21, 2009 at 10:10 AM

    I agree with Ben Pate's suggestions, but think there could be a use for some type of savecontent(var=&quot;x&quot;) { } functionality. I don't think we need output processing within a function if we can build the output either manually or with a savecontent().

    Output processing with-in the same block of code made sense in a tag-based environment. I'm not so sure it fits in a scripting / function based environment; I'm open to being convinced otherwise however.
  • 116 Aaron Neff // May 21, 2009 at 10:33 AM

    Regarding 'cf'tagname().. For consistency &amp; backward compat, 'cf' might need to be &quot;allowed&quot; for *all* (ex: cfLen(), cfNow(), cfWriteLog(), cfDecrypt(), etc). Meaning, cfImageRead() would be the same as imageRead(), and wouldn't break code.

    Yes, the 2 'cf' characters may seem redundant. If we add new functions directly into the top-level namespace w/o a prefix, then we may have backward compat issues. If we only prefix new functions, then we have inconsistency issues.
  • 117 Anand Paleja // May 21, 2009 at 10:43 AM

    Can you add the ability to use a &lt;cfml&gt; tag? Where we could switch from cfscript to cfml, basically the inverse of what we have now.

    Maybe have a cfc by default be in cfscript and we can optionally switch to cfml using the &lt;cfml&gt; tag? ( I dont want to have to close cfscript, do my tag based logic and then reopen cfscript in order to do it. )

    For example:

    public void processMsg( struct msgStruct ) {

    doSomething();
    doSomethingElse();

    &lt;cfml&gt;
    &lt;cfmail to=&quot;...&gt;
    msgStruct.text
    &lt;/cfmail&gt;
    &lt;/cfml&gt;

    }

    I still think we need full support in cfscript but I would use the cfml version if it was easily available for instances like cfmail and cfquery.
  • 118 Patrick McElhaney // May 21, 2009 at 11:00 AM

    &quot;If we are prepared to give that up, we could just force people to concatenate strings and pass those to mail() as body= or query() as sql= and ignore savecontent() altogether.&quot;

    YES!

    Don't muddle the whole language for the sake of cfsavecontent(). It doesn't belong in cfscript anyway.

    If you want to mix code into a multi-line string, call out to CFM file.

    recentTweets = cfmodule(template=&quot;tweetPod.cfm&quot;,data=tweets)


  • 119 Marko Simic // May 21, 2009 at 1:24 PM

    @Ben Pate Well spoken Ben. +1

    One more &quot;big pro&quot;, imo, is if cfscript adopt OO aproach, that will make easer to OO-programmers to get use to CF(script). And vise versa, it will make easer to cf-developers to learn pure OO-languages after cf(9).
  • 120 anthony // May 21, 2009 at 1:36 PM

    @Scott G., My if, for and while statements do have curly braces, but those are control flow statements. mail and savecontent should be functions. My main issue with it is readability from an outsiders perspective.
  • 121 Adam Ness // May 21, 2009 at 2:13 PM

    @Patrick Actually, saveContent has a pretty good place in cfscript, since it could be used to do string concatenation using mutable strings, instead of immutable strings like most concatenation.

    For example, consider the following code snippet:

    var string = &quot;Hello&quot;
    for( var i = 0; i &lt; 100; i++ ) {
    string = string &amp; &quot;o&quot;;
    }

    vs.

    var string = saveContent() {
    writeOutput(&quot;Hello&quot;),
    for( var i=0; i&lt; 100; i++ ) {
    writeOutput(&quot;o&quot;);
    }
    }

    The first one creates 101 strings in memory, then has to garbage collect all but one of them. (1st, &quot;Hello&quot;, then &quot;Helloo&quot;, etc... )

    The second creates 1 string builder, and then appends &quot;Hello&quot; and then &quot;o&quot; to it 100 times. Creating only one object, and not garbage collecting it is way faster.

    I've actually run into performance problems when using string concatenation before, which should be a concern for the language architects.
  • 122 Patrick McElhaney // May 21, 2009 at 5:55 PM

    @Adam, in that case, just use a StringBuilder().
  • 123 Marko Simic // May 22, 2009 at 1:19 AM

    @Patrick McElhaney You've stolen my thought! :)
    ...or maybe you could use SaveContent()

    SaveContent()

    var sBuilder = saveContent();
    sBuilder.append(&quot;Hello&quot;);
    for( var i=0; i&lt; 100; i++ ) {
    sBuilder.append(&quot;o&quot;);
    }

    they could &quot;just&quot; create a wrapper for java.lang.StringBuilder, name it SaveContent or CFSaveContent and voila.
  • 124 Justin Carter // May 22, 2009 at 2:20 AM

    Re: @Ben Pate's comments:

    &quot;The proposals for adding &lt;tags&gt; directly into script are elegant, but I think it would be too confusing for everyone involved. The CFEclipse plugin has a hard enough time parsing my files as it is. And I feel the sam about the &quot;tag() {body}&quot; suggestions.

    I fear that these solutions would be elegant, but are a big departure from the keep-it-simple philosophy that has made CFML so great. I don't see how this would be easy to explain to a new developer&quot;.

    I don't think E4X-style syntax is &quot;confusing&quot; or a &quot;departure from the keep-it-simple philosophy&quot; of CFML at all, because it's identical to the same tag based syntax that we *have* to use now, except for &quot;variableName = &quot; at the start of the line and a semi-colon at the end of the statement.

    Plus it opens up new possibilities for a native XML type and XML literals, *and* solves the problem of how to handle output from custom tags if you want to use them within a cfscript block.

    We can't solve cfmail and cfquery unless we solve custom tags at the same time, and in a consistent manner, because at the end of the day they are all just tags with attributes, nested tags and a tag body.


    In addition to that, turning cfmail or cfquery into an object with setable properties and an execute() function only serves to make the syntax *more* verbose than the tags that we started with (or the E4X-style proposal), as do the suggestions where writeOutput() is plastered everywhere to handle text output. I wouldn't want to use a solution that requires more work than the &quot;problem&quot; we are trying to solve, when cfscript is supposed to be more concise. (Also, the curly braces in your &quot;JSON-style&quot; example aren't needed).
  • 125 Clint // May 22, 2009 at 7:01 AM

    The fact is that it needs to be consistant with the rest of the cfscript syntax.

    var exampleParam = &quot;an example.&quot;;
    var mymail = structNew();
    var mailparam = structNew();
    mailparam.file = &quot;C:\Inetpub\wwwroot\web.gif&quot;;
    mailparam.disposition = &quot;inline&quot;;
    mailparam.contentID = &quot;image1&quot;;
    mymail.mailparam = mailparam;
    mymail.from = &quot;me&quot;;
    mymail.to = &quot;you&quot;;
    mymail.subject = &quot;New cfscript mail function test.&quot;;
    mymail.body = &quot;This is &quot; + exampleParam + &quot;&lt;br&gt;Image: &lt;img src='cid:image1'&gt;&quot;;
    mymail.query = queryResults;
    mailResults = writeMail(mymail);

    var myquery = structNew();
    var qp1 = structNew();
    qp1.value = &quot;1&quot;;
    qp1.cfsqltype = &quot;CF_SQL_INTEGER&quot;;
    qp1.maxlength = 10;
    myquery.name = &quot;qCreate&quot;;
    myquery.datasource = DSN.getName();
    myquery.query = &quot;select &quot; + getFields() + &quot; from mytable where id = &quot; + validateQueryparam(qp1);
    queryResults = writeQuery(myquery);

    Problem solved, case closed. Next!
  • 126 Adam Ness // May 22, 2009 at 9:30 AM

    @Marko that's a really good suggestion. I hate when the answer to a question in ColdFusion is &quot;Just shell out to java, and use it's functionality&quot;. If that were really the answer, CFImage and CFDocument should never have been added to CFML. CF is all about wrapping up the java syntax and making it easier to use, so if we could simplify using a stringBuilder in a way that you don't have to read the javadocs, and get CreateObject(&quot;Java&quot;) opened up on your shared host, then that's a huge advantage to lots of devs (both CF and &quot;other brace/semicolon&quot; developers)
  • 127 Charlie // May 22, 2009 at 11:59 AM

    Re: Justin Carter's comment

    One thing to keep in mind is that cfscript is more concise at things like logic, variable assignment, and function definitions is because it doesn't mix in text output with code. And it's that distinction, which works so well in those contexts, that makes it less elegant with these new cases.

    I know that in my case I prefer to program logic flow in script, and the reason I look forward to having all the language available in script is so I don't have to break out of it to do a &lt;cflocation&gt; or the like.

    E4X does seem like a powerful tool, but honestly it feels weird to me. However, weird doesn't mean bad, and if that's the direction that it goes, I'll probably like it OK.

    The main thing that I don't want to see happen is to see a &quot;pure&quot; OO syntax for query and mail. The closest parallel to cfquery and cfmail (and cf tags in general) in scripting syntax is a self-invoking function. To have two different paradigms of language design in cfscript (OO) and &lt;cfml&gt; (functional) would be very awkward.

    Currently, the main difference between cfscript and cfml is just syntax, and that's how I think it should stay.
  • 128 Robert Gatti // May 22, 2009 at 12:59 PM

    I'm not sure if anyone has brought this up yet but how would you convert the following more complicated example into script? This has three sets of body content with the cfmail, cfloop, and cfif that has to be evaluated. So far from what I've played with syntax wise just in notepad nothing really looks like an elegant solution.

    &lt;cfmail to=&quot;someone@abc.com&quot; from=&quot;service@abc.com&quot; subject=&quot;Your order&quot;&gt;
    Your order on #dateFormat(now(), 'short')# has this stuff:

    &lt;cfloop query=&quot;order&quot;&gt;
       &lt;cfif order.putInEmail&gt;   #productName# &lt;/cfif&gt;
    &lt;/cfloop&gt;
    &lt;/cfmail&gt;
  • 129 Sean Corfield // May 22, 2009 at 3:50 PM

    @Robert, yes, that is the core problem that we're really trying to solve. That's why several of the suggestions here don't work too well - and why the committee is still looking for more elegant answers...
  • 130 Marko Simic // May 22, 2009 at 4:27 PM

    Charlie's comment actually opened my eyes :)
    &quot;Currently, the main difference between cfscript and cfml is just syntax, and that's how I think it should stay.&quot;
    After 9 years working in CF I was never looking on cfscript that way. But, on &quot;second&quot; thought,he could be right. And if he is right, than cfscript is nothing more but signed confession of people in Allaire/Macromedia that they failed.
    Really. If you have a good product (cftags),why you are creating the same product without basic element - element because everyone like it (tags)?
    What I want to say. Macromedia/Adobe decided long ago to push CF to OO-way. Why we would change the track now? Keyword &quot;new&quot; is going to be introduced in CF9. What is &quot;new&quot; but &quot;operator used to create new object&quot;?

    If you stop following an idea on the half of the road, you'll make more damage then that road is wrong. So, if you decided to translate (cf)tags to &quot;curly braces&quot;, then do it no matter how &quot;elegant&quot; that is or not. If you want to follow an OO-idea (CFC and all about it), then do that and use new &quot;new&quot; ;)

    This start being confusing and I apologize if I am contributing :)
    Good luck.
  • 131 Ryan Cogswell // May 22, 2009 at 4:58 PM

    @Sean The list of comments in here is now so long, it would be helpful if you (or someone else on the committee) could take the time to summarize in a single posting the main different options that have so far been proposed and perhaps listing what the committee would see as the pros/cons of each. It would also be useful to indicate which of those options are almost certainly out of the running so that future comments can be more focused on either options that no one has yet considered or refinements of the options that are already on the table.

    On a side note -- I was indeed quite surprised (and still a little confused) by the result of wrapping a multiline string in quote-pound-quote. I'm pretty sure I understand why it didn't cause a syntax error, but the resulting output (truncated to the first line) seems very strange to me.
  • 132 Mark Jones // May 22, 2009 at 5:22 PM

    I wonder if we are trying too hard to make a straight conversion of tag -&gt; script. After all, there really isn't a tag version of &lt;cfloop&gt; Is it even possible to do something like for( query ) { writeOutput(query.id) } ?

    The object-like syntax is tempting because it's the closest way to &quot;build up&quot; the same structure you'd be able to do with tags. I admit the approach doesn't seem to merge well with the existing script mentality.

    If you don't have an object-style interface, you'll need to have a function with tons of named parameters (and/or an explicit &quot;options&quot; parameter, like PHP) to allow for all the various options.

    As far as traditional script styles go, that's it. Anything else and you're inventing syntax that doesn't yet exist in CF. That would include the E4X and the mail(){{ ... }} stuff.

    The pure functional approach has to look *something* like this:

    mail(to,from,cc,bcc,subject,body,mailparts=[ mailpart(type,charset,wraptext,body), mailpart(type,charset,wraptext,body) ], mailparams=mailparam(file) );

    The only variations are in parameter order and how to handle the zero-to-many nature of the mailpart and mailparam. Query is similar:

    query(datasource, sql, queryparams=[ queryparam(value, type) ]);

    In all these cases, the &quot;nested&quot; functions don't actually *do* anything, they're just a nice shorthand for creating configuration. Maybe they simply return some sort of configuration object (maybe just a struct) that is passed into the core function for final processing. Eg queryparam(&quot;15&quot;,&quot;CF_SQL_INTEGER&quot;) would just return {value=&quot;15&quot;,cfsqltype=&quot;CF_SQL_INTEGER&quot;} maybe with some additional data needed by the engine for whatever purpose.

    I'm sure the committee has looked at all sorts of variations of the above, but I would be very shocked if the final result was much different.

    As an aside, with the large number of paramters such functions might need, does the existing standard allow for mixing positional and named parameters? Could we have:

    queryparam( &quot;15&quot;, cfsqltype=&quot;cf_sql_integer&quot; );

    That way we can put the most common few parameters in the beginning in a logical order, and then not have to memorize the order of EVERYTHING. (The cfmail tag itself has 27 attributes... do you want to see ,&quot;&quot;, &quot;&quot;, &quot;&quot; 20 times before you can specify &quot;wraptext&quot;?)

    This cfscript conversation has really got my brain turning in the script/tag interaction area... it's hard to restrict myself to the question at hand. :)
  • 133 Patrick McElhaney // May 23, 2009 at 11:07 AM

    @Robert, that's easy. You would do it by assembling the body beforehand:

    mailbody=&quot;Your order on #dateFormat(now(), 'short')# has this stuff:\n&quot;;

    for (order in orders) {
    if (order.putInEmail) orderBody &amp;= &quot;productName\n&quot;;
    }

    cfmail(to=&quot;someone@abc.com&quot;,from=&quot;service@abc.com&quot; ,subject=&quot;Your order&quot;,body=orderBody)

  • 134 Charlie // May 23, 2009 at 1:32 PM

    Re: Marko's comment:

    &quot;Macromedia/Adobe decided long ago to push CF to OO-way. Why we would change the track now?&quot;

    I just wanted to highlight that there's a distinction between a language that can be used for OO programming and a language that is built on objects.

    ColdFusion is currently built with tags, which are definitely not objects, and yet it can just as definitely be used to build object oriented applications.

    Whether the core library/functionality of a language is exposed as objects or functions doesn't determine the types of applications that can be built. That's determined by the language's features.
  • 135 Michael Steele // May 27, 2009 at 10:46 AM

    I just want to jump in here and bring up the object concept. I'll be honest, I haven't read all the comments so hopefully I'm not repeating too much.

    1) I don't think you can have your cake and eat it too. If you want to make cfscript more robust by adding more syntax, and keep more CFers on the language, it is possible that you will have to also adopt some of the 'gotchas' (if you will) of the languages and style that cfscript is trying to parallel. Personally, I don't have any problem creating objects when I need to do something. It's difficult to tell coders that they need to be more &quot;object oriented&quot; and then remove the need for them to ever work with them. ?? ;-)

    2. Another approach to the problem might be to only the parts that need to have access to nested code as object. A DynamicCode object, which could be passed to the cfscript function.

    block = new DynamicCode( &quot;select * from table where column=&lt;cfqueryparam ... /&gt;&quot; );

    query( dsn=&quot;foo&quot;, sql=block );

    This is very similar to the E4X-style solution mentioned earlier, but seems a bit cleaner from an interpreter standpoint. It keeps the cftag -&gt; function concept but doesn't require the coder to remember which tags don't follow that rule. It also provides a consistent way to do nested tags across syntax.

    Just my $0.02

  • 136 Charlie // May 27, 2009 at 11:49 AM

    Re: Michael Steele's comment:

    &quot;It's difficult to tell coders that they need to be more &quot;object oriented&quot; and then remove the need for them to ever work with them.&quot;

    I may be wrong, but I don't think it's the intent of the advisory committee to tell CF developers that they need to write object-oriented applications.

    I think their intent is to provide more and better tools for developers. That's why they're rounding out cfscript and adding new ways of working with objects -- because these are useful tools that are requested by the community, not because Sean Corfield or Ben Forta have declared that OO is the One True Way for CF Developers.
  • 137 Sean Corfield // May 28, 2009 at 9:35 AM

    @Michael, one thing to bear in mind is that:

    dynamicCode( &quot;some #variable# in here&quot; )

    The variable will be evaluated before that &quot;function&quot; is called according to the rules of CFML. It's that sort of thing that makes this so problematic.
  • 138 Michael Steele // May 28, 2009 at 11:43 AM

    @Sean,

    Well then, without changing the interpreters parsing algorithms, is it acceptable from a syntax standpoint to escape the #'s? Such that (for example):

    dynamicCode( &quot;some ##variable## in here&quot; )

    isn't translated, but passed into the init of the dynamic code object, (or body of the dynamic code function if your semantics are different) so that you can basically create runtime includes? I realize you might want to use something else, but it sounds like whatever solution you come up with is going to introduce a somewhat new concept ( or at least a new implementation of an existing concept), so new syntax wouldn't be so jarring.

    Granted it would probably still attempt to evaluate the following: dynamicCode( &quot;some data &lt;cfif foo&gt;bar&lt;/cfif&gt;&quot; );

    It may be that dynamically created text blocks have to be created in a step before the function call. Then if you have a particularly gnarly text block, using the cftags becomes more appropriate.
  • 139 Charlie // May 28, 2009 at 12:05 PM

    @Sean

    Correct me if I'm seeing this wrong, but it looks like the problem breaks down like this:

    We don't want &lt;cfscript&gt; to be ridiculed by Java/.NET folks because it's too different, but at the same time we don't want to lose the powerful abstractions that CFML currently has. So we're looking for some fancy-looking silver bullet that we can whip out to reply to them, &quot;But look how COOL this is!&quot;

    The safest thing to do is &quot;what everyone else does,&quot; pass a pre-built query string and an array of parameters and query.execute()! But fortunately it seems the committee realizes this is a step down from what already exists in &lt;cfquery&gt;, where CF magically transforms my &lt;cfqueryparam&gt;'s into question marks and adds the values to the parameters array in the right order. I also don't have to remember to tell it to execute()! It can read my mind!! Now THAT'S cool!

    So what's the hang up? Why don't we model &lt;cfscript&gt; after CFML? Seems like a great idea to me, so what's involved? Well, look at what &lt;cfquery&gt; does:

    1) It parses the code inside the tag block, replacing any &lt;cfqueryparam&gt;'s with '?' and populating an array with those values, and then saving the resulting text output of the tag block as the query string.

    2) It then passes the generated query string and parameters array to some underlying Java query object (presumably), along with any applicable tag attributes.

    Take away step 1, and you're left with no advantage over Java/.NET. So let's keep Step 1--and our advantage. So what's the closest way to match &lt;cfquery&gt; in &lt;cfscript&gt;?

    MyQuery = Query(_Tag Attributes Go Here_) {

    ..WriteOutput(&quot;

    ....SELECT My, SQL, Goes, Here

    ....FROM MyTable

    ..&quot;);

    ..if(DatePart('d',Now()) % 2) {

    ....WriteOutput(&quot;WHERE TheDay = #QueryParam('#Form.Odd#',cf_sql_varchar)#&quot;);

    ..}

    }

    Its only weakness compared to &lt;cfquery&gt; is that you need to explicitly specify text output, while retaining all the other advantages of &lt;cfquery&gt; over the competition. That's nothing new, though. In all scripting languages you have to specify text output, as far as I know. It's certainly not worse than string concatenation. Are we afraid of someone saying, &quot;OMG! You have to use WriteOutput() just to execute a query! LOL!&quot;?

    It also helps with code structure. If all the logic and SQL for my query is inside a Query() {} block, it's immediately apparent which query I'm working on. But if I pre-bake my query string to pass into an object, then it's not necessarily obvious which Query object this &quot;sqlstring&quot; variable applies to, at least without glancing a second time.

    This simple idea would also address the same problems with mail() and savecontent(). And I've noticed you throwing out &quot;gotchas&quot; for many of the other proposals, but I have yet to see you bring one up against this idea, except that it's &quot;ugly&quot;.

    I'm all for using silver bullets when they're available, that's why I use ColdFusion, but I would caution against over-engineering the problem. Sometimes it is the simplicity of the concept that makes it beautiful.
  • 140 Michael Steele // May 28, 2009 at 1:36 PM

    @Charlie

    Interesting. Wonder how much work would be required in the interpreter to figure out that you aren't defining a function called Query(){} that's being assigned to MyQuery.

    Programmatically it seems sound. Do you think that the syntax being too similar to how you code functions would be confusing?

    function myQueryFunc( args ) {
    ...code
    }

    myQuery = query( args ) {
    ... code
    }
  • 141 Charlie // May 29, 2009 at 7:00 AM

    @Michael

    I don't think the similarity would be confusing. To me, curly braces just signify that &quot;this is a block of code&quot; that for structural or functional reasons needs to be packaged in a little syntax box. Such as in implicit struct creation:

    myStruct = {

    ..var1 = &quot;value1&quot;,

    ..var2 = &quot;value2&quot;

    };

    And the format CommandName(){...} just signifies that this is a block of code that can take some parameters:

    if(args){...code}

    for(args){...code}

    while(args){...code}

    function(args){...code}

    query(args){...code}

    And aside from that, I think that you could explain it to a CF developer with as little effort as saying, &quot;It's just like &lt;cfquery&gt;, but with curly braces and WriteOutput(),&quot; and then showing them a side-by-side example. No new concepts, just a little bit of syntax to learn.
  • 142 Brian OConnor // Jun 2, 2009 at 12:19 PM

    Sometimes I wonder where CFML is going. To me &quot;forcing&quot; a cfscript OO model is just making the whole thing look Java like. The line is getting blurred more and more and it is almost to the point that it would be just as easy to use Tomcat (or any other JSP/Servlet container) as it would be to use CF. With a Java environment one already has full OO with a similar syntax to what I have seen in this post and it also has an extensible tag implementation.
    I have seen many arguments within the CF community around being fully XML compliant (for example &lt;cfset var=&quot;foo&quot; value=&quot;bar&quot;/&gt;) and to better implement objects. I think at some stage someone has ask what is the real benefit of CFML and how do we ensure its continued success.

  • 143 Marcel // Jul 26, 2009 at 10:52 PM

    +1 for e4x or c4x.

    Native xml would be so highly benefitial, you could build the most truly mvc site. I would love to have a single html file with everything in it and be able to just strip stuff out based on id tags if it isn't needed and push content into it from the database also based on xml node id. It would be so much easier for designers.

    That is the only way I can see cfml competing well in future with pure Javascript servers using DOM manipulation/e4x syntax.