I want to discuss one item of the cfscript improvement conversations happening recently that I disagree with. I think most agree that Adobe's cfscript tag implementation in CF11 is unnecessarily confusing:
cftag(attr=1, attr2=2) { ... }
Adam gives his opinion that tags requiring a body could be implemented as functions that accept a closure:
tag(attr=1, attr2=2, function(){
...
});
Some related posts:
I am of the opinion however that I like the Railo implementation of tags:
tag attr=1 attr2=2 {
...
}
These are my reasons for liking Railo's implementation:
1) We already have CFML <cf> tags and for better or worse they are here to stay. Railo's implementation requires just dropping of the "cf" and this keeps the language consistent from both ends.
2) Tags with bodies mean that there is an expectation of executing a code block which also implies block nesting. I think function passing for the purposes of creating code blocks is actually a relatively ugly style and Railo has a unique advantage. Take this comparison for example:
tag(function(){
anotherTag(function(){
});
})
VS
tag {
anotherTag {
}
}
Further then, why should 'native' code blocks only exist for traditional blocks of if/switch/try/else? If function-block style is superior, why not design a language that looks like this?
if(1<3,function(){
try(function(){
}, catch=function(){
})
})
The reason we wouldn't like that is because of historical momentum for what we are used to, it would be unnecessary boilerplate for the common case, and it would also look like shit.
So I'm asking, why pepper the code with extra "function()" syntax to achieve the same thing we already have today? I think the Railo version is much cleaner. In fact, I want Railo to double down and make CFML custom tags work fully in cfscript syntax as above so that we can do more natural DSLs in script. Take for example the testBox callbacks:
function run(){
describe("A Spec", function(){
beforeEach( function( currentSpec ){
// before each spec in this suite
});
afterEach( function( currentSpec ){
// after each spec in this suite
});
});
});
Instead of that callback soup, I'd love to be able to implement something clean with custom tags in cfscript:
function run(){
describe title="A Spec" {
beforeEach {
// before each spec in this suite
}
afterEach {
// after each spec in this suite
}
}
}
3) If the reason for moving to callbacks is to be more 'mainstream', I don't think that will win any hearts. Anyone who wants this style might as well jump ship now.
I instead want Railo to be an easy to learn, batteries included, high performance JVM web application platform. That is its only market potential. Railo/CFML will never catch up to any of the other mainstream languages. The declarative syntax, BIF library (as opposed to traditional OO package import), built in services (ORM, Rest, S3, Caching, Search), parity between script and tags all come together to make a complete and flexible package. In fact I would like Railo to update and increase its function library and core services further to make it even easier for modern applications.
I agree with the fact that some tags simply don't translate well (cfparam, cfquery) but so what? At least the current implementation is mostly straight forward, and really only screwed up by ACF. I also agree that in general no new self closing tags should be added to the language, and instead that functionality should only be added as functions going forward. But any tag which fits a nested execution block style, well why the hell not keep doing it the Railo way?
There are use cases for features implemented as native bock style, regular BIFs, or function passing/callback style. Use the best method for the job. I like that Railo has all three and I really don't see the problem, what am I missing?
Rory