Sunday, 8 December 2013

CFML: For the sake of completeness: createLocalisedDayOfWeekAsInteger(): a closure approach

G'day:
A coupla days ago I continued my TDD / unit testing series with an article "Unit Testing / TDD - refactoring existing code". This engendered a few comments, none of which paid any attention to the intent article, instead focused on something pretty much irrelevant to what I was discussing. This engendered this reaction from me:


Oh how I love my readership sometimes. But, actually, the comments got me thinking...

That article covered the approval process for CFLib of a function dayOfWeekAsInteger(), which is the reverse of dayOfWeekAsString(): it takes a string (in English only), and returns which day of the week that corresponds to, starting with Sunday as the first day. Why does it start on Sunday instead of Monday (as per ISO 8601)? Because it's the inverse of dayOfWeekAsString(), and that's how that does it. Is that right? Well: no. Is that relevant to either this UDF or the blog article? Also: no.


However James's suggestion for how Simon could rewrite his function to suit James's requirements (James: write your own functions if you want them different from how others have implemented them!) did get me thinking about how to do it. A thought popped into my head that one could leverage closure to create a function which was specific to a given locale. This might not be exactly what James wants, but it was what I decided to look into, because it's slightly interesting, and covers a feature of closure I've not covered anywhere on this blog yet. So it interests me.

Saturday, 7 December 2013

500: to put things in perspective

G'day:
In August, Ray posted this: "Over 5000! (Almost...)".

So it puts things into perspective that this is only my 500th article. Still: I've only been going for 513 days, so that ain't bad. Almost one per day (obviously the content is variable though!). I was only really aiming for one a week - concerned I'd run out of things to say - so I'm doin' all right, really.

And, no, I will not remind you every 100 articles (I did an article at 400 too: "Bad Request"). But I probably will remind you @ the 1000 mark. If I get there.

Cheers for reading & commenting & stuff.

--
Adam

CFML weirdness with chr(0)

G'day:
I was trying to help someone on Stack Overflow y/day with their question "How to pad a string with null/zero-bytes in ColdFusion & difference between CF on MacOS and Windows". The question is actually shorten than the title: how to add null characters to a string in CFML.

I thought the answer was a simple "use chr(0)", but this turned out to not be a viable answer on ColdFusion (or Railo for that matter).

In response to my suggestion, Stack Overflow veteran Leigh made the observation "Unfortunately no. The character just disappears. But URLDecode("%00") will generate a single null byte". I've not known Leigh to be wrong so I didn't doubt him, but that sounded really odd, so I decided to check it out.

<!--- baseline.cfm --->
<cfset s = "test" & chr(0)>
<cfoutput>
string: [#s#]<br>
length: [#len(s)#]<br>
</cfoutput>

And the - surprising to me - output:

string: [test]
length: [4]


Um... where gone?

I tried this on Railo... thinking Railo's more likely to get it right than CF is, and it had the same output. Testing on OpenBD got what I'd consider to be the correct results:

string: [test]
length: [5]


The NULL isn't printable, so doesn't render anything, but it should still actually be there, and that string should consist of five bytes: 0, 116, 101, 115, 116. That's a length of five. As per OpenBD's output.

That said, I know that NULLs do have special meaning in some strings, for example C has the concept of a null-terminated string, in which the null signifies the end of the string, not a character in the string. I wasn't aware of this being a "thing" in Java, but maybe it was.

I refined my code somewhat to not be simply end-padding the string:

<!--- outputStringContainingChr0.cfm --->
<cfset s = chr(0) & "foo#chr(0)#">
<cfoutput>#s#:#len(s)#:#asc(left(s,1))#</cfoutput>

So I'm sticking a NULL at the beginning and end of the string. If it was acting as a terminator, s would simply be an empty string afterwards. But I get this (CF and Railo both):

foo:3:102

102 is indeed the ASCII code for f.


So what's the story here? I still had a suspicion that something "non-stupid" was happening here, and I just didn't get it. Maybe there's something about a NULL char's standard handling that means it's not added to strings. Although this seems far-fetched as obviously there's use-cases for it (see the Stack Overflow question), and indeed Leigh came up with the fudged way to do it:

Groovy: G'day World

G'day:
I'm investigating some ColdFusion stupidity (more on that after this article), and as part of my comparison of the behaviour in other languages, I figured I should also test on another JVM-based language. And given all the adulation of Groovy at the moment, and an exceptional presentation "Grails/Groovy Primer for ColdFusion Developers" from Scott Stroz, I decided to D/L and install Groovy.

Warning: this will be a short article, and will only take me as far as getting "G'day World" onto the screen. It's really aimed at CFMLers like myself who never find time to do anything else, and just a demonstration as to how quick this all was.

Previously I've written up similar exploits on PHP: "PHP: from zero to... Hello World" and Ruby: "Ruby: stream-of-consciousness".

OK, so here's what I did to get Groovy up and running on my machine:

CFML: Response for Russ

G'day:
I feel like writing more in response to Russ than Twitter messaging will sensibly allow, so am doing a quick blog article instead.

The context is as follows:



Note that the RT's of Matt's messages aren't quite in the correct order, but as his Twitter account is "private" (that was easily circumvented ;-), I cannot include them inline in a custom timeline. But the gist of the exchange is preserved.

Right, so I feel the decline of CFML as a language is mostly down to Adobe's stewardship of it. There are a few factors here:

Friday, 6 December 2013

Unit Testing / TDD - refactoring existing code

G'day:
I've just had a new submission in the CFLib queue, and as it's an easy one to test and release, I'm gonna jump on it and get it out there today. However I want to test it first, plus I want to refactor it slightly, so I'm gonna use TDD to do so. And document what I'm doing as I go.

This continues a series on unit testing and TDD that I'm doing, the rest of which are tagged with either "Unit Testing" or "TDD" or both, so you can look them up via those links (there's too many to list now, so I won't bother).

The code for this article will be here: https://github.com/daccfml/scratch/tree/master/cflib/dayOfWeekAsInt (only the baseline files are there at the moment, as I haven't written the code yet ;-).


A question in more than 140 characters

G'day:
I'm just wondering what you think, and can't fit the question into a Twitter message.

Say I have a function which takes a string, and returns the numeric represent of that string in the context of a set list of values. EG: the function is dayOfWeekAsInt() takes "Monday" and returns 2 (Monday being the second day of the week). What should the function do if it receives invalid input, say "Moonday"?

I'd err towards raising an exception, but another option could be to return 0. On one hand "Moonday" is not a valid input, so an exception is good response. On the other hand "Moonday" has no index in the context of the series Sunday-Saturday, so I can see a case for zero too.

Thoughts?

--
Adam