Showing posts with label Closure. Show all posts
Showing posts with label Closure. Show all posts

Thursday, 3 November 2016

PHP: different ways of defining one-off objects

G'day:
This one came from a Stack Overflow question I watched be raised, commented-on and summarily closed again because there are rules to follow, and by golly the community moderators on S/O looove following rules.

Anyway, the question got asked, but never answered.

'ere 'tis:

In PHP 7, what's the use of stdClass with the availability of anonymous classes?


As of PHP 7 we have access to anonymous classes. This means we could ditch stdClass when we need generic object as a return value... But which one would be cleaner?
  • What other differences are between those two guys?
  • Is there any performance drawback on creating an anonymous class? i.e. as each one has a different "class name", is there any additional impact?
  • Do both work "the same way" from the developer point of view, or are they actually two different beasts in some cases?
<?php
$std_obj = new stdClass(); //get_class($std_obj) == 'stdClass'
$anonymous = new class {}; //get_class($std_obj) == 'class@anonymous\0file.php0x758958a3s'

Good question. Well the bit about performance ain't, cos at this stage of one's exploration into these things - asking initial questions - one clearly doesn't have a performance issue to solve, so just don't worry about it.

OK, so I like messing around with this sort of thing, and I still need to learn a lot about PHP so I decided to refresh my memory of the various approaches here.

Firstly, the "anonymous classes" thing is a new feature in PHP 7, and allows one to model objects via a literal expression, much like how one can define a function via an expression (making a closure) rather than a statement. Here's an example:

$object = new class('Kate', 'Sheppard') {

    private $firstName;
    private $lastName;
    
    public function __construct($firstName, $lastName){
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }
    
    public function getFullName(){
        return "{$this->firstName} {$this->lastName}";
    }
};

See how go new class, and then proceed to define the class right there in the following block. Note this doesn't create a class... person1 does not contain a class; it creates an object. As evidenced by my subsequent usage of it:

echo $person1->getFullName();

Output:

Kate Sheppard

TBH, I dunno about the merits of this. In PHP one can already declare classes in the same file as other code, and more than one class in the same file. I guess it's handy for when one needs to define a one-off modelled object within another function or something? I dunno.

The other version mentioned was via stdclass, but let's not go there yet.

Now bear in mind the OP was asking about creating empty objects. One can do that with an anonymous class by just not giving the class definition any body:

$empty = new class(){};

Dumping that out gives:

object(class@anonymous)#1 (0) {
}

And with stdclass:

$empty = new stdClass();

Dumping that out gives:

object(stdClass)#1 (0) {
}

Not much to it. But I dunno if the intent in PHP is to use stdClass directly. The docs just say:

Created by typecasting to object.

It doesn't say "instantiate one of these to create an empty object". And that's where it'd say it, if that was the intent.

What it does allude to is this:

$empty = (object) [];

Dumping that out gives:

object(stdClass)#1 (0) {
}

(so same as with stdClass). To me the intended usage of stdClass is just one of inference. An array cast to an object needs to be of some type, so there's stdClass to accommodate that.

Also: how often does one want an empty object, and that's it? At least with casting an array to an object one can give it some properties off the bat:

$person = (object) [
    'firstName' => 'Kate,
    'lastName' => 'Sheppard'
];

One can add properties to the object afterwards with a new stdClass(), but that seems clunky.

Thinking about it, using new stdClass() seems about as right a way to do things as using array() to declare an array, as opposed to using a literal []. Bleah. Just use the literal.

But this all got me thinking though. Empty objects be damned. How can I implement the same as that anonymous class using these other syntaxes.

I managed to write some really crap code implementing analogues using stdclass and an object literal.

First the object literal, as it's not too awful:

$person2 = (object) [
    'firstName' => null,
    'lastName' => null,
    '__construct' => function ($firstName, $lastName) use (&$person2) {
        $person2->firstName = $firstName;
        $person2->lastName = $lastName;
    },
    'getFullName' => function () use (&$person2) {
        return "{$person2->firstName} {$person2->lastName}";
    }
];

It's not sooooo bad. Until one ones to try to use it. Check this out:

$person2->__construct('Emmeline', 'Pankhurst');
echo $person2->getFullName() . PHP_EOL;

This just gives:

PHP Fatal error:  Uncaught Error: Call to undefined method stdClass::__construct() in literalVsObjectCast.php:37
Stack trace:
#0 {main}
  thrown in literalVsObjectCast.php on line 37

Yikes. This turns out to be some weirdo order of operation things, and I can't quite remember what the story is, but it's down to how and what the function call is bound to the function, and the -> operator taking precedence over the () operator. Or something.

It's easily enough solved:

($person2->__construct)('Emmeline', 'Pankhurst');
echo ($person2->getFullName)() . PHP_EOL;

See how I've used parentheses there so the method calls are on the reference to the object/method. This works:

Emmeline Pankhurst

But it's unorthodox code, so I'll be avoiding that. Oh yeah, also notice the weirdness I had to do with the reference with the closure there. Plus having to reference the object's properties by this "external" reference. Still: good to be able to do it though.

We can go from "unorthodox" to "shit" now. There's the equiv using stdclass:

$person3 = new stdclass();
$person3->firstName = null;
$person3->initial = null;
$person3->lastName = null;
$person3->__construct = function ($firstName, $initial, $lastName) use (&$person3) {
    $person3->firstName = $firstName;
    $person3->initial = $initial;
    $person3->lastName = $lastName;
};
$person3->getFullName = function () use (&$person3) {
    return "{$person3->firstName} {$person3->initial}  {$person3->lastName}";
};

And again to run it, we need to use those extra parentheses:

($person3->__construct)('Susan', 'B', 'Anthony');
echo ($person3->getFullName)() . PHP_EOL;


Susan B Anthony

It's all a bit grim for words: the literal version was a bit awkward, but this as all the awkwardness as well as a lot of clutter (and, yes, this version also supports a middle initial, but that's not really the bulk of the bloat).

Another thing with these latter two versions is that - until the class literal version - firstName and lastName are public. I guess it's no big thing for throwaway objects, but it seems a bit "leaky" to me.

One of these JavaScript tricks we learn when trying to fit the oval peg into the round hole that is "doing OO in JS", is the Module Pattern: using an IIFE to emulate an object with private data. PHP 7 also added IIFEs, it already has closure, so we can do this in PHP too:

$person4 = (function($firstName, $lastName){
    return (object)[
        'getFullName' => function() use ($firstName, $lastName){
            return "$firstName $lastName";
        }
    ];
})('Vida', 'Goldstein');


And running it:

echo ($person4->getFullName)() . PHP_EOL;

Output:

Vida Goldstein

Now I reckon that's the tidiest syntax of all! Even beating the anonymous class version. But one is still stuck with those extra parentheses on the function call though. Pity.

In conclusion, I reckon this:

  • if you want an empty object... use (object)[]. Don't use a mechanism - anonymous classes - specifically intended to derive fully modelled objects, just to create empty objects.
  • If you want a throw-away object with a few public properties in it it: still use (object) []. It's tidier and less typing.
  • If you need some methods in there as well... go for the anonymous class literal; its usage syntax is more orthodox than using the IIFE.
  • But do remember PHP7 has IIFEs! They come in handy for things other than emulating JS design patterns.
  • I don't reckon one ought to directly use stdClass. It's clunky, leads to bloated code, and the docs kinda position it as a necessary implementation, not something that one's supposed to actively use.
  • But... generally speaking use a proper named class. These anonymous classes are not a replacement for them; they're for throw-away objects. You'll seldom need those.
  • Don't start an exercise worrying about performance. Write good clean code, using TDD, and worry about performance if it comes up. And differences like this are never gonna be where to make savings anyhow.

Thoughts? Obviously I'm just a relative n00b at PHP so I might be missing some important thing that seasoned PHPers all "get" but I've not come across yet. Lemme know.

Righto.

--
Adam

Tuesday, 12 April 2016

JavaScript: getting my brain further around bind()

G'day:
I was refactoring some JS code today, and one of the refactorings was extracting an inline callback into its own separate function. This was the "success" callback for a jQuery AJAX request. The reason I wanted to pull it out of its inline situation was twofold:

  1. the function it was in was already way too long;
  2. it itself was a bit on the long side, and had a few "moving parts", and I wanted to extract it so it was testable.
I hasten to add we don't have any JS testing in place yet, but I like our code to be positioned to be testable for making our lives easier once we bring it in. It occurs to me now that this is an example of premature optimisation in a way, but the remit of the work I was doing was precisely this, so I figure it's OK. What's more... I've currently got time to do this, and later on when someone comes to need to do maintenance on this code they might not have time to wade through layers of nested complicated logic, so now is a good time to tidy up a bit.

I can't use our actual code to demo what's going on here, but I've done a reduced proof of concept which demonstrates the point without all the distracting baggage.

The existing situation was this sort of thing:

var usingInline = function(firstThree, fourth, type){
    var allFour = firstThree;
    allFour.push(fourth);
    var prefix = type;
    allFour.forEach(function(element){
        console.log(prefix + ": " + element);
    });
};

var oneTwoThreeInMaori = ["tahi", "rua", "toru"];
var fourInMaori = "wha";
usingInline(oneTwoThreeInMaori, fourInMaori, "Number");

That code will run as it stands, and outputs:

Number: tahi
Number: rua
Number: toru
Number: wha


No AJAX call here, but there's an inline callback buried in the middle of it. Truth be told with a callback this small, I'd just leave it there in real life, but that would make for a short, pointless blog article. My task here is to extract that callback.

As is my occasional wont, I did not pay attention to what I was doing and just ripped the callback out into its own function, and replaced the inline call to it with the name of the new function:

var usingExtracted = function(firstThree, fourth, type){
    var allFour = firstThree;
    allFour.push(fourth);
    var prefix = type;

    allFour.forEach(eachHandler);
};

var eachHandler = function(element){
    console.log(prefix + ": " + element);
};

var oneTwoThreeInMaori = ["tahi", "rua", "toru"];
var fourInMaori = "wha";
usingExtracted(oneTwoThreeInMaori, fourInMaori, "Number");

And that goes... splat:

Uncaught ReferenceError: prefix is not defined(…)

Why? Cos in the first example we were leveraging closure: the function expression was declared in the context of the usingInline function, so it enclosed the prefix variable, so it was available to use within the callback code. Closure in action. Whereas with the second example, eachHandler is declared in the global document context (well: it was within a class in the original code, but same thing applies: it was a different context from that which prefix was defined), so prefix was not there to close over, so it was not available.

Duh.

Prior to a week or so ago, my way of handling this would be to still declare the handler separately (so it's still testable), but instead of calling it directly, wrapping it in an inline function which does nothing but wraps a call to it, in the process enclosing prefix, and passing it into the handler. Like this:

var usingWrapper = function(firstThree, fourth, type){
    var allFour = firstThree;
    allFour.push(fourth);
    var prefix = type;

    allFour.forEach(function(element){
        eachHandlerToUseWithWrapper(prefix, element);
    });
};

var eachHandlerToUseWithWrapper = function(prefix, element){
    console.log(prefix + ": " + element);
};

Note that the handler now takes a prefix argument too, instead of just the argument forEach() passes to its callback.

That's all good. It's a bit "Heath Robinson", but it works.

A few weeks ago I wrote that article "JavaScript: clarifying in my head this and that and proxies" about proxying this in JavaScript callbacks. One of the techniques I looked at was using bind() to bind a different this to a function. One of the things I did not investigate but recalled reading about was that it can also be used to pass additional arguments into the function it returns. This is exactly what I want, and it was quick to knock together:


var usingExtractedWithBind = function(firstThree, fourth, type){
    var allFour = firstThree;
    allFour.push(fourth);
    var prefix = type;

    allFour.forEach(eachHandlerToUseWithBind.bind(undefined, prefix));
};

var eachHandlerToUseWithBind = function(prefix, element){
    console.log(prefix + ": " + element);
};

Here I'm not interested in proxying this as I don't need it in the callback, so I just leave it undefined (this was from the docs, and seems reasonable, but I would not have guessed to do this), and simply specify prefix as a value to pass into the function bind() creates. Then I use the same callback as before with both the prefix argument, and the element that forEach() passes in. What bind() is doing here is basically the same as in my previous example: it's making a new function, which receives the prefix value as its first argument, and then receives whatever other args are passed to it. Cool!

Perhaps not earth-shattering for you lot, but this was the first time I put this into action, so it's kinda the more interesting "TIL" from today (I had a few today actually... but I'll get to them one at a time).

There's a working JSFiddle of this code here.

Righto.

--
Adam

Saturday, 5 September 2015

Expectation management: mapping a changing array

G'day:
I've been staring at this code (/variations thereof) for a week or so now (since JavaScript: running Jasmine unit tests from the CLI; more specifically my JavaScript version of the code I rewrote from "Some CFML code that doesn't work"). I noticed an idiosyncrasy in the first JavaScript version of that code which didn't make sense to me at first. And I ass-u-me`d that my previous expectations made sense and JavaScript was being weird. Then I ran the equivalent code in some other languages and now... not so sure. So here we are: I'm writing a blog article about code I'm not sure I'm completely comfortable with.

It does not help that I'm on my eighth pint of Guinness for the afternoon. But perhaps only as far as my typing goes (which is proving to be a real challenge).

Here's the general gist of what I was trying to do with CFML:

// closure.cfm

letters = ["a","b","c","d","e"];
remappedLetters = letters.map(function(number,index){
    var localCopyOfTheseLetters = duplicate(letters);
    letters.deleteAt(1);
    return localCopyOfTheseLetters;
});
remappedLetters.each(function(series){
    writeOutput(series.toList(" ") & "<br>");
});

Don't worry so much about running that: it does not do what I want (mostly), but more what I'm trying to do, and my expectations of the results.

What I want from this code is to iterate over the letters array, and for each element of it return the whole array from that point. So I'm not really using the callback's value, I'm just leveraging the fact that the map() iteration method loops over each element of the array, so I get to defined - element by element - its replacement.

On Lucee - which is what I tested this with - I get what I want:

a b c d e
b c d e
c d e
d e
e


And this is what I mentally leveraged when working out my code for that "Some CFML code that doesn't work" article. The rest of my logic was predicated on that approach working.

When I tried the same logic on JavaScript:

// closure.js

var letters = ["a","b","c","d","e"];
var remappedLetters = letters.map(function(number,index){
    var localCopyOfTheseLetters = letters.slice();
    letters.shift();
    return localCopyOfTheseLetters;
});
remappedLetters.forEach(function(series){
    console.log(series.join(" "));
});

I get a different result:

C:\src\otherLanguages\js\arrays\map\changeOriginal\js>node closure.js
a b c d e
b c d e
c d e

Huh? Why does it stop after three element? I'm iterating over a five-element array after all. I surmise that under the hood JavaScript is using some sort of Iterator.next() operation. Given I am changing the array I'm iterating over via closure, by the time I get to the third iteration of my map() call, I've lopped two elements off the array, so its length is three, so the map() process exits when Iterator.next() rechecks where it is in the array, and finds out it's at the end. This is entirely supposition, but it seems reasonable.

But initially I was thinking "dumb-arse JavaScript, if I call a method on an object, then the method should be called on the object's current state!". This makes sense for a one-off method, but does it make sense for an iterative method? Hmmm. I had not thought about that. And I had no answer, and given my two comparative cases (Lucee, JavaScript) behaved differently, I didn't know what ought to be the "right" answer. And by "right" I mean "industry standard". I erred towards JavaScript being right, and Lucee being wrong.

Running this example on ColdFusion behaves like JavaScript. But to be honest: I back Adobe to get things right even less than I do LAS, so I filed that as "nice to know".

I did my usual thing of testing out my limited repertoire of other languages running equivalent code.

Sunday, 9 August 2015

PHP 7: specifying the context for closure to use

G'day:
Here's a cool new feature of PHP 7 that doesn't seem to have been spouted off about as much as other things like speed (oh, I don't know if anyone has mentioned: did you know PHP 7 is faster than PHP 5? I'm not sure if anyone's mentioned that. In the last 5min, anyhow) and "spaceship operators". In PHP 7 one can specify the context to which a closure should bind to with a single method call.

Here's an example. The code below just calls a closure using the usual approach:

<?php
//demo.php

class A {
    private $v = "A OBJECT CONTEXT\n";
    private $closureToInject;

    function __construct($b){
        $this->b = $b;
        $this->injectClosure();
    }

    private function injectClosure(){
        $this->closureToInject = function(){
            return $this->v;
        };
        $this->b->injected = $this->closureToInject;
    }

    function callDirectly(){
        return ($this->b->injected)();
    }
}

class B {
    private $v = "B OBJECT CONTEXT\n";
    public $injected;
}


$b = new B();
$a = new A($b);

echo $a->callDirectly();
  • The bulk of this is just getting two disconnected environments which each have their own $v property: one in the A class, and one in the B class.
  • B has a public property which we can inject a closure into if we so choose (we do).
  • In A we define a function expression (which uses closure) which simply echoes the value of the $v property.
  • And then we call said function.

Monday, 25 May 2015

Some CFML code that doesn't work

G'day:
I was sitting at Lord's yesterday watching England v NZ (and, um, we'll have no comments about that, thank-you very much), and a sudden thought popped into my head "Adam Presley might've been onto something there... if I leverage that....I wonder if I could get that code down to one statement?"

And that of course will mean nothing to anyone.

Wednesday, 8 April 2015

Lucee 5 beta: "lambda" syntax

G'day:
Right, so the second thing I'm gonna look at (after yesterday's "Lucee 5 beta: static methods & properties") is Lucee's new "Lambda" syntax.

This syntax is simply a more terse syntax for defining functions using function expressions. TBH, it's not very interesting.

Tuesday, 4 November 2014

PHP: array_udiff()

G'day:
I'm not too sure how interesting this article is gonna be, but for the last coupla days I've been trying to solve a problem using array_udiff() to filter elements from one array based on their sameyness (I made that word up, sorry) compared to elements in another array. Now I know this perhaps isn't quite the intended purpose of a diffing function - and it turned out to not be a viable solution for this reason - but the investigation turned up some "interesting" behaviour that isn't clearly documented as far as I can tell.

First things first, look at this shambles:

Saturday, 1 November 2014

PHP & CFML: mapping and reducing

G'day:
I'm trying my hardest to answer PHP questions on StackOverflow these days, but the PHP community is so large and my PHP knowledge is so neophytic that I am never an early-enough bird to catch the worm for the easy questions. Plus a lot of the "PHP" questions are actually asking framework specific questions, and I have no idea about Laravel, Zend etc.

Still: I found an interesting question today with a pedestrian answer, so I decided to offer my own answer (to the actual question as asked). The answer would have been easy in CFML, but it was a bit of a ball-ache in PHP.

Thursday, 16 October 2014

CFML: Gert points out a schoolboy error in my prime numbers generator logic

G'day:
I was messing around with using closure to mimic a generator the other day: "CFML: prime number generator UDF, and overhead of using inline function expressions". Gert had a look at it, and spotted a shortfall in my implementation. He's provided some code as well but I've not really looked at that yet, instead wanting to nut it out myself (part as a penance, part as an exercise).

Sunday, 12 October 2014

CFML: prime number generator UDF, and overhead of using inline function expressions

G'day:
I continued to play around with faux generators in CFML after I finished "CFML: emulating generators with closure" yesterday. Whilst I didn't think the world would benefit from there being a palindrome generator on CFLib.org, it might benefit slightly by having one that generated primes. CFLib.org already has a function which returns an array of primes up to a threshold (GetPrimes()), but that's a slightly different requirement than being able to generate them one at a time. And I wanted to fiddle about anyhow, so that became my mission.

The actual code is not mention-worthy in and of itself, but a coupla things I noticed along the way probably are.

Friday, 19 September 2014

Answering my first PHP question on Stack Overflow

G'day:
It's really quite interesting. With any CFML question someone might ask me, I am brimming with confidence (or bravado, perhaps), am self-assured, and have no problem either backing myself to be correct, or happy to say "dunno, but I'll find out". I've decided I had better start answering PHP questions on Stack Overflow, as answering questions is a really good way to learn stuff. Especially if one doesn't know the answer to start with.

Wednesday, 3 September 2014

Wrong wrong wrong, Cameron is wrong

G'day:
Adam Tuttle and I were talking on IRC about some of my code today - in the context of closure - and I brashly asserted the code might implement closure, but it didn't actually use it, so it was a bad example of closure in action (like, admittedly, almost all examples people use when demonstrating it).  I further posited I could simply use declared functions instead of inline function expressions and the code would still work, thus demonstrating my case.

TL;DR: I was wrong about that. But it doesn't sit entirely well with me, so here's the code.

Wednesday, 23 July 2014

CFML: Finally had a chance to look at Sean's version of case()

G'day:
This took way longer to revisit than I intended. Apologies to Sean, as it might have seemed like I solicited some code from him and then ignored it. And, indeed, that was mostly the case other than an initial peek and a "hang on... what? How the? But... oh, I think I see..." and a conclusion my assessment of it needed more than 2min.

Right, so a coupla weeks back I wrote and article "Some more TestBox testing, case/when for CFML and some dodgy code". This demonstrated some code (and its tests) that I was messing around with that implemented a case/when/then/else function in CFML. That'll make more sense if you read the article.

Sean had a look at it and could see some simplifications which could be made, and popped a revised version through to me via Github ("adamcase / case.cfm"). As I alluded to above, my initial parsing of the solution just made my eyebrow raise - Spock-like - and other than that I saw what he was doing, but not how it worked (and it did work; the relevant tests still passed). Today I sat down and had a look at the code, and made myself understand it. And I like it.

Here it is:

Friday, 11 July 2014

Quickly: read Sean's comments and code

G'day:
I said this on Twitter last night, but in case you're wise enough not to busy yourself with that sort of nonsense, I'll repeat it here.

A few days ago I posted some woolly code which implemented a case / when in CFML ("Some more TestBox testing, case/when for CFML and some dodgy code"), and solicited help in improving it.

Sean's leapt to the fore and reworked it in a much more clean fashion. His comments start here, and there's links to his code. He's put a lot of effort into it, and I'm quite chuffed he's taken the time that he has.

So thanks, Sean. And everyone else: you could learn a thing or two by comparing my effort and his approach to tidying it up.

I haven't analysed his code thoroughly myself yet - I've just had no time - but will be doing so over the weekend, and will write up my conclusions.

Again: thanks Sean.

--
Adam

Wednesday, 9 July 2014

Some more TestBox testing, case/when for CFML and some dodgy code

G'day:
This is an odd one. I was looking at some Ruby code the other day... well it was CoffeeScript but one of the bits influenced by Ruby, and I was reminded that languages like Ruby and various SQL flavours have - in addition to switch/case constructs - have a case/when construct too. And in Ruby's case it's in the form of an expression. This is pretty cool as one can do this:

myVar = case
    when colour == "blue" then
        "it's blue"
    when number == 1 then
        "it's one"
    else
        "shrug"
end

And depending on the values of colour or number, myVar will be assigned accordingly. I like this. And think it would be good for CFML. So was gonna raise an E/R for it.

But then I wondered... "Cameron, you could probably implement this using 'clever' (for me) use of function expressions, and somehow recursive calls to themselves to... um... well I dunno, but there's a challenge. Do it".

So I set out to write a case/when/then/else/end implementation... as a single UDF. The syntax would be thus:

// example.cfm
param name="URL.number" default="";
param name="URL.colour" default="";

include "case.cfm"

result =
    case()
        .when(URL.number=="tahi")
            .then(function(){return "one"})
        .when(function(){return URL.colour=="whero"})
            .then(function(){return "red"})
        .else(function(){return "I dunno what to say"})
    .end()

echo(result)

This is obviously not as elegant as the Ruby code, but I can only play the hand I am dealt, so it needs to be in familiar CFML syntax.

Basically the construct is this:

case().when(cond).then(value).when(cond).then(value).else(value).end()

Where the condition can be either a boolean value or a function which returns one, and the value is represented as a function (so it's only actually called if it needs to be). And then when()/then() calls can be chained as much as one likes, with only the then() value for the first preceding when() condition that is true being processed. Clear? You probably already understood how the construct worked before I tried to explain it. Sorry.

Anyway, doing the design for this was greatly helped by using the BDD-flavoured unit tests that TestBox provides. I could just write out my rules, then then infill them with tests after that.

So I started with this lot (below). Just a note: this code is specifically aimed at Railo, because a few things I needed to do simply weren't possible with ColdFusion.

// TestCase.cfc
component extends="testbox.system.BaseSpec" {

    function run(){
        describe("Tests for case()", function(){
            describe("Tests for case() function", function(){
                it("compiles when called", function(){})
                it("returns when() function", function(){})
            });
            describe("Tests for when() function", function(){
                it("is a function", function(){})
                it("requires a condition argument", function(){})
                it("accepts a condition argument which is a function", function(){})
                it("accepts a condition argument which is a boolean", function(){})
                it("rejects a condition argument is neither a function nor a boolean", function(){})
                it("returns a struct containing a then() function", function(){})
                it("can be chained", function(){
                })
                it("correctly handles a function returning true as a condition", function(){})
                it("correctly handles a function returning false as a condition", function(){})
                it("correctly handles a boolean true as a condition", function(){})
                it("correctly handles a boolean false as a condition", function(){})
            })
            describe("Tests for then() function", function(){
                it("is a function", function(){})
                it("requires a value argument", function(){})
                it("requires a value argument which is a function", function(){})
                it("returns a struct containing when(), else() and end() functions", function(){})
                it("can be chained", function(){})
                it("executes the value", function(){})
                it("doesn't execute a subsequent value when the condition is already true", function(){})
                it("doesn't execute a false condition", function(){})
            })
            describe("Tests for else() function", function(){
                it("is a function", function(){})
                it("requires a value argument", function(){})
                it("requires a value argument which is a function", function(){})
                it("returns a struct containing an end() function", function(){})
                it("cannot be chained", function(){})
                it("executes when the condition is not already true", function(){})
                it("doesn't execute when the condition is already true", function(){})
            })
            describe("Tests for end() function", function(){
                it("is a function", function(){})
                it("returns the result", function(){})
                it("returns the result of an earlier true condition followed by false conditions", function(){})
                it("returns the result of the first true condition", function(){})
            })
        })
    }
}

TestBox is cool in that I can group the sets of tests with nested describe() calls. This doesn't impact how the tests are run - well as far as it impacts my intent, anyhow - it just makes for clearer visual output, and also helps me scan down to make sure I've covered all the necessary bases for the intended functionality.

I then chipped away at the functionality of each individual sub function, making sure they all worked as I went. I ended up with this test code:

Monday, 9 June 2014

CFML enhancement: alternate function expression syntax; "lambda expressions"

G'day:
In this article I just want to - hopefully - extend the audience of a conversation taking place on the Railo Google Group ("Railo 5 lambda expressions"). Even if you're a ColdFusion developer (ie: only use the Adobe product, not the Railo one), this will still be relevant to you as Railo generally leads CFML development these days, so innovations they make will - perhaps some time in 2016 - make it into ColdFusion's dialect of CFML.

There are a lot of good brains in the CFML community, and I hope to encourage some more of them to join this discussion.

Saturday, 12 April 2014

Bugs in iterator functions in both Railo and ColdFusion

G'day:
I decided to "do my bit" for the cfbackport project, and am looking at implementing the new collection iteration functions for older versions of ColdFusion. I'm aiming for CMFX6.0 onwards, but am having to guess at some of the language restrictions as I'm on my back-up laptop and only have CF10 & 11 to test with.

Friday, 11 April 2014

Railo 4.2.0.007 is out: more new iteration methods

G'day:
Micha posted on the Railo Google Group the other day "(Last) Railo beta release (4.2.0.007)". You can get this via the in-admin updater if you're set to use the "Development releases (Bleeding Edge)" update channel.

Staying true to form, the upgrade process is seamless, and it also offers a bunch of excellent new stuff, as well as bug fixes. This is definitely the way CFML should be heading... not waiting around two years between features, as we have been with ColdFusion.

There's a swag of new stuff, but I'm just gonna focus on the added iteration methods: for queries and lists.

ColdFusion has had some list iteration functions since ColdFusion 10, and adds more in ColdFusion 11. I discuss them in "ColdFusion 11: .map() and .reduce()". Railo hadn't implemented them, I think because they - somewhat dogmatically - don't consider lists to be a "type", therefore only consider string functions to be appropriate for strings. This is slightly specious IMO because Railo does have all the other list functions, after all. Anyway, they've added them now.

Here's example usage of the list-iteration member functions: .each(), .filter(), .every(), .some(), .map(), .reduce(). They have not implemented a list-sorting iteration function, for some reason. This code is also on GitHub: list.cfm.

rainbow = "whero,karaka,kowhai,kakariki,kikorangi,tawatawa,mawhero"

"first,second".each(function(){
    dump(arguments)
})

rainbow.each(function(element,index,list){
    echo("#index#/#listLen(list)#: #element#<br>")
})

Sunday, 30 March 2014

Railo: I've got to the bottom of that code I asked you to test for me

G'day:
Thanks to everyone who helped out with my challenge in this article: "Railo: help me replicate a bug I'm seeing on one of my machines". I think the reason I was seeing the difference in behaviour is twofold:
  1. I'm a dropkick;
  2. Railo's setting "Local scope mode" (which I can't find docs to link to [grumble], so I'll need to explain it).
The reason why I suspect I'm a dropkick is that I think this is all down to my machine at work having "local scope mode" set to "modern", whereas every other instance I have been looking at is set to "classic". I do not recall switching my work machine to use this setting (and I'll be switching it off as soon as I sit down at it on Monday), but it seems like this is what the difference is.

Thanks to Gert for pointing me in the direction of the various Railo "make Railo work differently from ColdFusion" settings that Railo has.

Wednesday, 26 March 2014

Using a sort iteration function to implement a custom ranking

G'day:
It occurred to me last night that - in all my examples of using a callback-based sort on a collection - I am always just using the natural ordering of a field; eg I sort an array of structs on a key in the struct which needs either alphabetical or numeric sorting. EG:

numbers = [
    {maori="wha", digit=4},
    {maori="toru", digit=3},
    {maori="rua", digit=2},
    {maori="tahi", digit=1}
]

dump(numbers.sort(function(v1,v2){
    return sgn(v1.digit - v2.digit)
}))


This is selling the functionality short, somewhat.