Railo 4.0.3 Railo not finding un-scoped variables in arguments when undeclared in method signature

99 views
Skip to first unread message

br...@bradwood.com

unread,
Jan 18, 2013, 3:36:38 PM1/18/13
to Railo List
Here's another that I might not have even noticed if it wasn't that it's an incompatibility with ACF.  I have Googled and searched JIRA as well as the known incompatibility guides and didn't immediately find any specific information.  I did find a Google Group thread from 2010, but it didn't really have any resolution.

I'll start with the code sample that works on ACF, but errors on Railo 4.0.3.

function callme() {
    writeOutput(foo);  // errors "variable [FOO] doesn't exist"
}

callMe(foo='test');

Basically, if I dump out the arguments scope, I can see foo in there but I have to do one of two things to be able to access it: always write out arguments.foo, OR declare the foo parameter in the function.  Railo's scope hunting behavior doesn't seen to pick up arguments that weren't declared in the function.

Under Railo Scope settings, I have "Cascading" set to "Standard (CFML Default)" and "local scope mode" to "update (CFML standard)" so I would expect the same behavior as ACF in this regard.

As usual, I would like to enter a compatibility ticket, but I'm posting here first to find out if there is any more back story on this behavior or missing documentation that I haven't found.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: br...@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com 

Matt Quackenbush

unread,
Jan 18, 2013, 3:48:47 PM1/18/13
to ra...@googlegroups.com
I don't know whether or not that is an intended "incompatibility", but I do know that that is horrible code, and, in my humble (yet extraordinarily accurate) opinion Railo has the correct behavior.

Igal @ getRailo.org

unread,
Jan 18, 2013, 3:50:32 PM1/18/13
to ra...@googlegroups.com
LOL @ humble!

Bruce Kirkpatrick

unread,
Jan 18, 2013, 5:43:14 PM1/18/13
to ra...@googlegroups.com
Brad, what about running it this way?

callMe(argumentcollection={foo='test'})

I actually built my MVC controller system in such a way where all of the controller method arguments that exist are automatically mapped to the function in order based on the metadata for the function.  Any extra arguments are thrown into an "extraArguments" struct so that they could be processed differently and I use argumentcollection to send everything to the method.   It's probably cleaner to have separate functions though since this creates a kind of undocumented public API.

function callMe(param1, param2){
if(structkeyexists(arguments, '_zExtraArguments')) and structkeyexists(arguments._zExtraArguments.param3)){
   writeoutput('param3 is:'&arguments._zExtraArguments.param3);
}
}

The mvc url
/controller/method/param1/param2/param3



Brad Wood

unread,
Jan 19, 2013, 12:34:04 PM1/19/13
to ra...@googlegroups.com
Lol, thanks for your humble opinion.  :)

Unfortunately, whether or not you prefer code that looks like my repro case is orthogonal to the discussion of compatibility.  The point is, the repro case demonstrates syntactically valid CFML and the expectations of that code are all documented by Adobe.

UDFs accept "optional, undeclared arguments."

"If you use a variable name without a scope prefix, ColdFusion checks the scopes in the following order to find the variable:"

Railo's behavior does not match ACF's documentation or actual behavior in this case.

Thanks!

~Brad

Matt Quackenbush

unread,
Jan 19, 2013, 12:51:33 PM1/19/13
to ra...@googlegroups.com


On Jan 19, 2013 11:34 AM, "Brad Wood" <br...@bradwood.com> wrote:
>
> Lol, thanks for your humble opinion.  :)

You're welcome. :-)

>
> Unfortunately, whether or not you prefer code that looks like my repro case is orthogonal to the discussion of compatibility.  The point is, the repro case demonstrates syntactically valid CFML and the expectations of that code are all documented by Adobe.
>
> UDFs accept "optional, undeclared arguments."
> http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSc3ff6d0ea77859461172e0811cbec0a66e-7fe2.html
>
> "If you use a variable name without a scope prefix, ColdFusion checks the scopes in the following order to find the variable:"
> http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7fdf.html
>
> Railo's behavior does not match ACF's documentation or actual behavior in this case.

I get that, I really do. However, I believe that Railo should not concern itself with being compatible on silly things that ACF does. The silly things - there are many - are largely why CFML gets the bad rap that it does.

At this point in time, Railo is the very clear leader in the CFML world. It is my very strong opinion that Railo should not care about ACF, because doing so will do nothing but hold Railo - and therefore CFML - back. In my opinion Railo should be after fixing the stupid stuff (i.e. not duplicate it) and expanding the language, which will do wonders for the community in terms of education and growth. I think it's an enormous mistake to try and cater to folks who just want to jump ship to get a free license, but can't be bothered to invest in their own code (and future) to fix the technical debt they've incurred over the years.

assertTrue( Railo != ACF )
assertTrue( Railo > ACF )

:-)

Brad Wood

unread,
Jan 19, 2013, 1:30:29 PM1/19/13
to ra...@googlegroups.com
I am (painfully) aware of the sentiment you expressed being prevalent in some members of the Railo community.  

Honestly, I think this specific example is really not too far fetched.  Basically Railo _does_ scope-hunt, but only in _some_ scenarios which is inconsistent.  I don't think you can chalk this entirely up to "ACF just being silly" since to rectify Railo's own inconsistencies you would need to do one or both of the following:
  1. Stop allowing undeclared arguments in UDF (I can't imaging using CFML without that)
  2. Stop allowing any form of scope hunting and force everything to be explicit. (Again, there are select situations in which I really enjoy the readability afforded by having less cluttered code)
I would suggest, that in the event that Railo doesn't want to give up undefined UDF arguments nor scope hunting, the two should simply work.  Period.  You can't blame this on ACF.  

That aside, I want to comment that I do recognize your sentiments as valid and even though I see if differently, I would be in support of Railo if they truly decided to stop worrying about ACF compatibility.  My frustration with this is two fold though:
  1. The sentiment is not unified.  There are discrepancies between how members of this community feel on the matter, and frankly I'd like to see everyone on one side or the other.  (yes, I know-- a pipe dream most likely)
  2. To date, the most prominent indications are that Railo does care about compatibility (with a handful of documented exceptions) and advertises itself as such.  If the final answer ever is "we don't care about ACF compatibility" then I would expect the "ColdFusion® compatibilty version" to be removed from the Railo admin home page, and I would expect things like "CFML Standard" settings to be removed from the Scope page.  I think it's easier for people coming into the platform to have an all or nothing expectation.  
In other words, let's be committed towards making it work, or let's not bother advertising it.  Both are are valid options, but I don't want Railo to advertise compatibility, yet have to fight tooth and nail every time it doesn't work.  (And I'm more-than-happy to donate fixes for these things since I realize this is an open source community where people give of their free time to make this product a reality).

Thanks!

~Brad

Matt Quackenbush

unread,
Jan 19, 2013, 1:35:52 PM1/19/13
to ra...@googlegroups.com

I agree with you that the compatibility text should be removed. 100%. :-)

Igal Sapir

unread,
Jan 19, 2013, 2:26:57 PM1/19/13
to Railo List

As a general rule: Railo does care about compatibility.

Igal

--
typos, misspels, and other weird words brought to you courtesy of my mobile device and its auto-(in)correct feature.

Bruce Kirkpatrick

unread,
Jan 19, 2013, 2:42:29 PM1/19/13
to ra...@googlegroups.com
2. Brad, I'm actually spending dozens of hours forcing this explicit improvement across the important parts of my application because this makes CFML very fast and more "secure" in terms of code not polluting the variables that other functions are using.    There are also cases where query variables in CFC are read differently from ACF I believe, which can cause some bizarre side effects when you fail to scope things well.   

Railo is only breaking compatibility on a very few obscure bad programming related issues in my experience.   Do I want it to break compatibility with Coldfusion?  We'll all benefit from allowing coldfusion developers to come to Railo with zero bugs, but I don't want to be annoying to these kind people who have provided an amazing product to the world at no expense to me.   Railo's deviations just need to be documented or made into admin options, but if they want to depriortize docs, that's cool.  I don't bother to doc anything myself.  Their approach to programming really mirrors mine - faster, from scratch, break some rules, get it done now, and clean it up later.  If they waited until true compatibility was perfect, we may have a 3-4 year release cycle, which is kind of why Adobe innovates so slowly.  They put a different level of polish at the expense of achieving less features & fixes in the same amount of time.  I have to deal with the same concerns in my multi-tenant application.  Do I change behavior or do I add a new option and fork the behavior in more ways.  Do I let the work go out a bit sloppy and quick fix any edge cases or do I spend another week testing every line of code again?  I tend to favor the slightly rushed, slightly inferior, but fast updates and lower cost approach.

All struct access is a Java hashmap under the hood with other behavior thrown on top of it.   When you do something like request.struct.struct.name, It actually has to lookup 4 different hashmap values in Java to get to the actual data.   Well, when you don't define a scope explicitly, it is sometimes equivalent to writing the entire application with deeply nested structs like that.     I challenge you to do a performance test of deeply nested structs vs a local variable access.  It is quite a massive difference in performance.  Railo has done a great improvement to the language by simplifying the local scope behavior.

Railo has the option to force local by default instead of variables scope, which fixes the massive problem with thread-safety/caching you get when relying on variables scope for everything.   I can't go live in production with this yet, but I am working through the issues in development currently with these incompatible scope options enabled.  It's great stuff.

Brad Wood

unread,
Jan 23, 2013, 2:14:13 PM1/23/13
to ra...@googlegroups.com
Ticket RAILO-2267 created.

Thanks!

~Brad

Michael Offner

unread,
Jan 23, 2013, 2:30:48 PM1/23/13
to ra...@googlegroups.com
what i personally really hate about ACF is, that it use the "=" operator for things like this:
bifCall(susi=x);
sct={susi=x};

i really hate to be compatible in this case, railo support from beginning also this syntax
bifCall(susi:x);
sct={susi:x};

and i would love to support only the ":" syntax, then for me the following 2 lines should be the same
susi=x;bifCall(susi);
bifCall(susi=x);

the assign operator should be a assign operator in any case!

coming back to the inital problem, we will look into it and it if has no impact (functionality or performace) of existing code, we could do that.

Micha




2013/1/19 Matt Quackenbush <quack...@gmail.com>
leader




--
/micha

Michael Offner CTO Railo Technologies GmbH

Brad Wood

unread,
Jan 23, 2013, 3:17:42 PM1/23/13
to ra...@googlegroups.com
For what it's worth, ACF 10 now supports using colons for assignments in struct literals.  I don't see them moving away from the equals operator though. 
http://www.carehart.org/blog/client/index.cfm/2012/3/7/charlie_areharts_ultimate_cf10_new_features_list

I personally hope you don't ever drop support for using = for named parameters the way it currently works.  That could make it rather difficult for frameworks to be cross-compaitble unless Adobe finally gets completely on board with using the colon.

Out of curiosity, are there other languages that would treat these two lines the same?
susi=x;bifCall(susi);
bifCall(susi=x);

> coming back to the inital problem, we will look into it...

Thanks.  I do think it makes the most sense regardless of compatibility.

Thanks!

~Brad



Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 



Peter Boughton

unread,
Jan 23, 2013, 3:42:51 PM1/23/13
to ra...@googlegroups.com

Brad wrote:
> Out of curiosity, are there other languages that would treat these two
> lines the same?

JavaScript would - it doesn't support calling functions with named arguments.



Michael Offner

unread,
Jan 24, 2013, 4:31:53 AM1/24/13
to ra...@googlegroups.com
No, I would love to get rid of = for name assignment, but of course we will not change that behavior in Railo and I'm sure ACF will never remove that.
For them the hurdle to update from one version to a other is extremely importend, this is how they make the money with ACF.

Out of curiosity, are there other languages that would treat these two lines the same?
susi=x;bifCall(susi);
bifCall(susi=x);
All I use (java,js,...), in Railo the = operator is like every other operator as well, like with every other operator you can use the result of the operation as expression, but this is not the case in ACF.

Take this example:
X=1+1/2*3; 
I can use the result of one operation directly as input for a other operation, because a operation is a expression ( Railo and ACF).
And because in Railo a assignment operation is a normal expression as well, you can do the following (Railo only).
X=1+y=3;

This example looks perhaps a little bit stupid, but I show you a example how I use this all the time.
while(Len(line=getline(...))){
Echo(line);
}
I just had to google "java example bufferedreader" and take the first link, to get a example for java
So believe me this is common practice in java.

ACF has similar problems with closures for no reason, you can assign a closure to a variable inside a script, but not use as expression?!
Example:
<cfscript>
var x=function (){};// works in Railo and ACF
</cfscript>
<cfset x=function (){}> works only in Railo
<cfdump var="#function (){}#"> works only in Railo

For me this makes no sense at all, operants of a operations are expressions, so this means a closure is a expression in Railo and ACF (see script example).
But if a closure is a expression, why is the second and third example not working in ACF?
I think the answer is very easy, the ACF closure implementation is more a patch integration, not done to the end.
Add closure support to Railo was not easy, because it has turned everything upset down, now a expression can contain statements.
We could implement this in Railo because our parser are handmade and extremely flexible, what perhaps is not the case in ACF.

Micha


Von meinem iPad gesendet

Adam Cameron

unread,
Jan 24, 2013, 4:55:51 AM1/24/13
to ra...@googlegroups.com


On Wednesday, 23 January 2013 19:30:48 UTC, Michael Offner wrote:
what i personally really hate about ACF is, that it use the "=" operator for things like this:
bifCall(susi=x);
sct={susi=x};

[...]

and i would love to support only the ":" syntax, then for me the following 2 lines should be the same


What I've never understood is why Javascript introduced the colon operator for struct-property-value assignment (and why people seem to want to perpetuate it). Everyone thinks it's fine to do this:

myVar = "myVar's value";

but some people rail against:

myStruct = {
 myVar = "myVar's value"
};

It's all still just variable assignment: a struct is just a compound variable, and the [entity] referenced by struct.key notation is, for all intents and purposes, still just a variable. Why the need for two operators which do exactly the same thing: assign a value to a variable?

(I'm not saying there isn't a distinction, I just don't get it).

--
Adam

Michael Offner

unread,
Jan 24, 2013, 5:25:27 AM1/24/13
to ra...@googlegroups.com
it makes totally sense, then a value assigned to a literal struct can be any expression, not only literals:

Example:
var person={key1:x=y+y}; 

Micha


2013/1/24 Adam Cameron <adamcamero...@gmail.com>

Alex Skinner

unread,
Jan 24, 2013, 5:38:08 AM1/24/13
to ra...@googlegroups.com
So in this example person.key1 would reference x ?

Must admit I don't understand either

Probably because I only do cf

A

Sent from my iPhone

Adam Cameron

unread,
Jan 24, 2013, 5:40:44 AM1/24/13
to ra...@googlegroups.com
That doesn't really make a case for what you're suggesting.

This already works fine:

<cfscript>
    y = 1;
    z = x = y + y;

    o ={
        z = x = y + y
    };
    writeDump(variables);
</cfscript>

Even if it didn't (and it doesn't in CF, and I will raise this as a bug with them), this does not explain the need for two different assignment operators.

If anything, it works against your case, doesn't it?

--
Adam

Mark Drew

unread,
Jan 24, 2013, 5:41:30 AM1/24/13
to ra...@googlegroups.com
In this example key1 == 2y (or x) 

I understand totally what Micha is saying. the "=" makes something equal something else, so x BECOMES 2y. 

the : ASSIGNS a value, like a pointer to the value. I guess the distinction would be the difference between "IS" and "REFERS TO"

Well, that is the way I think of it anyway. 


Regards

Mark Drew

The Railo Company
Professional Open Source
skype: mark_railo ma...@getrailo.com
+44 7971 852296 http://www.getrailo.com

Adam Cameron

unread,
Jan 24, 2013, 5:43:07 AM1/24/13
to ra...@googlegroups.com
The output of my example is this, Alex:

Scope
O
Struct
z
number2
X
number2
Y
number1
Z
number2

Basically a variable assignment itself is an expression, an expression which returns the value that was assigned.

--
Adam

Mark Drew

unread,
Jan 24, 2013, 5:43:35 AM1/24/13
to ra...@googlegroups.com
I think the example below would LOOK better if :

<cfscript>
    y = 1;
    z = x = y + y;

    o ={
        z : x = y + y
    };
    writeDump(variables);
</cfscript>



SO in this case, o IS a Struct, and o.z REFERS to x which IS y+y



Regards

Mark Drew

The Railo Company
Professional Open Source
skype: mark_railo ma...@getrailo.com
+44 7971 852296 http://www.getrailo.com

Adam Cameron

unread,
Jan 24, 2013, 5:47:33 AM1/24/13
to ra...@googlegroups.com
But - as far as I can tell - that's not what happens, Mark. Both operators do the same thing, just in different contexts. Both are assignment operators. You are assigning different descriptions to them in your head, but the distinction you're making only resides in your head (there's nothing wrong with that). It's a syntactical difference, not a functional difference.

From what I can gather, the only justification anyone has ever come up with for wanting the colon assignment operator in CF is because they do JS as well, and "get confused" when transitioning between the two languages. I have never heard any better justification / explanation than that. And that's a shit justification (IMO).

--
Adam

Adam Cameron

unread,
Jan 24, 2013, 5:48:52 AM1/24/13
to ra...@googlegroups.com
Well "looks better" is an aesthetic difference, and your explanation is a semantic difference, not a real difference :-(

I shall leave you chaps to it for a bit, as I have just been given some work to do. I hate it when that happens... ;-)

--
Adam

Mark Drew

unread,
Jan 24, 2013, 5:54:27 AM1/24/13
to ra...@googlegroups.com
Regardless of WHAT happens, we can define the syntax of the language which is a Good Thing(™) 

Yes they are assigning stuff, but one is a permanent state, the other is a pointer. 

On 24 Jan 2013, at 10:47, Adam Cameron <adamcamero...@gmail.com> wrote:

But - as far as I can tell - that's not what happens, Mark. Both operators do the same thing, just in different contexts. Both are assignment operators. You are assigning different descriptions to them in your head, but the distinction you're making only resides in your head (there's nothing wrong with that). It's a syntactical difference, not a functional difference.

From what I can gather, the only justification anyone has ever come up with for wanting the colon assignment operator in CF is because they do JS as well, and "get confused" when transitioning between the two languages. I have never heard any better justification / explanation than that. And that's a shit justification (IMO).
It can add power to your assignments. and clearer syntax is better. Since it shows intention. 

I haven't even referenced JavaScript. 

Mark Drew

unread,
Jan 24, 2013, 5:57:36 AM1/24/13
to ra...@googlegroups.com
It's also the context, as you are right they are the same thing but from WITHIN a structure it looks better, so for example:


y = 1;  // y becomes one! 

z = x = y+y // z and x both equal y+y


a =  {} ; // a equals a new struct
a.b = x // the key b in a equals x 

c  =  {
d: x
}

// the struct c has a KEY d with a value X

we are also used to this:

c = {

d = x; 
}


which in my mind is ok, but maybe not as descriptive? 




Regards

Mark Drew

The Railo Company
Professional Open Source
skype: mark_railo ma...@getrailo.com
+44 7971 852296 http://www.getrailo.com

Alex Skinner

unread,
Jan 24, 2013, 6:09:02 AM1/24/13
to ra...@googlegroups.com
Oh so does this mean that you can make a string value pass by reference rather than value.  

Does : behave differently to =

A

Sent from my iPhone

Michael Offner

unread,
Jan 24, 2013, 6:26:43 AM1/24/13
to ra...@googlegroups.com
"From what I can gather, the only justification anyone has ever come up with for wanting the colon assignment operator in CF is because they do JS as well"
then how you explain that since CF supports UDFs (CF5) the following syntax is supported:
<cfscript>
function test(a,b){}
test(b:2,a:1);// works in CF >=5
</cfscript>

this (named arguments) is something never was supported in JS.

for me this
{a:1}
is not a assignment operation inside the struct literal (and it definitely not is for the Railo expression parser!).
for me and the railo parser this is just a name declaration for a expression, in Railo this does not produce a variable named "a", it produced a namedargument that is passed to the constructor of the struct class, same for UDF or BIF calls.

if this would be a assignment, i wouls suspect that one of the following lines should work
sct={a=1,b=a};
sct={a=b,b=1}

then the a and b "assignment" are in the same namespace, right.
specially in JS, the in js you can use the "," to separate variable assignment as follows
var a=1,b=2;

the "," can be used to be in the same Environment declaration (var), 

Bruce Kirkpatrick

unread,
Jan 24, 2013, 11:37:36 AM1/24/13
to ra...@googlegroups.com
The strange colon syntax just reminds me of setting a type in actionscript and that syntax in actionscript is still bizarre looking compared to languages like java or c.  Wherever a space can be used instead of a character, that would look better.

The tag cfscript notation was the worst aesthetic addition to cfml, which must have added some more confusing parser complexity.

throw type="Ugly" message="Why, oh why this?";

I suppose this would have made the language more consistent:
throw({type="Ugly",message="Why, oh why this?"});

I don't know why = was added if colon : already worked.  That is insane. 

insane={a:"there", b="should", c:"be", d="one", e="way"}

I can't believe that works and I didn't know it works until you guys wrote about this.

Since colon predates the inclusion of :, the above examples should all be using colon instead then.

throw({type:"Acceptable",message:"Logic"});

sane={a:"there", b:"should", c:"be", d:"one", e:"way"}

If you wanted to aesthetically improve CFML with a compiler option to make insane syntax impossible, I'd agree with that.

Bruce Kirkpatrick

unread,
Jan 24, 2013, 11:39:21 AM1/24/13
to ra...@googlegroups.com
I think I meant this:
throw(attributeCollection={type="Ugly",message="Why, oh why this?"});

Bruce Kirkpatrick

unread,
Jan 24, 2013, 11:41:29 AM1/24/13
to ra...@googlegroups.com
I need to proofread better.  I meant colon predates equals sign.

Adam Cameron

unread,
Jan 24, 2013, 11:52:36 AM1/24/13
to ra...@googlegroups.com
Whichever you meant, it doesn't predate it anyhow. They were added @ the same time. UDFs in general were only added in CF5.

Bruce Kirkpatrick

unread,
Jan 24, 2013, 11:55:32 AM1/24/13
to ra...@googlegroups.com
I'm understand how equal in this statement is illogical.
var y=1;
var person={key1:x=y+y}; 

you'd end up with a struct that is only 
person.key=2;

But more insane is that x also becomes equal to 2.  That's even more insane when you consider a full example like this:

<cfscript>
var y=1;
var x=0;
var person={key1:x=y+y, key2:"test"}; 
writedump(person);
writedump(x);
</cfscript>
Reply all
Reply to author
Forward
0 new messages