Stuffing your stash with closures

The stash

Every request in Catalyst has a stash, which is scoped to that request.
It's accessed with the $c->stash accessor inside Catalyst, and made
available within whatever View you are using in your application.

For the purposes of this article, I'll concentrate on Template, i.e. TT,
but this technique is widely applicable.

The usual pattern is to stash various data (simple scalars, objects, arrays, etc)
during the course of your request, and you can then retrieve them (and for more
complex data, like objects, call methods on them), once inside your template.

Stashing closures

So, you can stash simple scalars, arrays and hashes (and then iterate through them later),
objects (which you can then call methods on later), but less obviously, you can stash code
references, and then call that code later..

Danger Will Robinson!!!

THE EXAMPLE ABOVE IS UNSAFE. It causes circular references!

Closing over $c (i.e. making a sub reference that includes $c inside it),
and then putting it into a data structure $c->stash which is directly
connected to $c, causes a loop, meaning that perl won't ever de-allocate
the memory.

If you do this once per request, then your application will quickly run out of memory!!

Whilst this looks somewhat more baroqe than the previous version, it won't leak any
memory, and is tremendously useful.

Sugar

The latest (0.36) version of Catalyst::View::TT has some syntax sugar to make
adding closures much easier. You don't get the flexibility of being able to change them
during the request cycle, but for most cases that isn't needed.

In your view configuration, you declare which methods on your view class will be exposed:

expose_methods => [qw/uri_for_css/],

and you then implement the method (in your View class), without having to worry
about circular references through the context object, E.g.

Further thoughts and ideas.

Other great things about a stashed closures is that you can have entirely different implementations
of them for different parts of your site (without needing to add a method on your MyApp object with
horrible conditional logic in it).

If you're using Chained dispatch, then you can fill in a default closure at the base of your
chain (for generic requests), and replace it with more specific versions later in the dispatch cycle
for more specific / customised parts of your application.

As the closures are code refs, it is in fact entirely possible to further customise them by wrapping
them inside another code ref which does some further work.

Conclusion

I hope this short article has opened your eyes to the potential useages for closures to clean up
repeated template logic fragments within your application, and given you some ideas for alternatative
ways to abstract specific fragments of display logic which don't really belong in your application templates.