Monthly Archives: January 2017

Crystal Language – Passing a closure (block) as a method/function argument.

So I’ve been working with crystal for a few weeks now and I’m still learning a lot of things about the language. One of those things that I had to figure out was passing a closure as a method or function argument.

Lets talk about PHP

Just to give you some background, I’m a php developer and we have a few primary frameworks out there and some of which you may have heard such as: Symfony, Zend Framework, CakePHP, Slim, Silex, etc… just to name a few. Now there’s a handful of frameworks and routers for crystal already, but they’re more catered to how you’d do things the ruby way and I’m not really comfortable with that style of coding. Not that there’s anything is wrong with that style of code, I just prefer to get things back to how I had things setup previously in my php workflow. Which brings me to how Slim Framework 3 handles routes. For example:

Here slimframework has this way to group routes in such a way that makes adding a ton of routes a bit easier when say we want to go back and change a base path. For instance, if the admin panel path changed we can wrap all the admin routes in a group then edit just the group without having to edit all our routes and call it a day.

Now a way to accomplish this in php is to pass a closure as a parameter and then bind the class to that closure where we can access all the class methods inside the current instance. Now the way you’d handle the grouping is by setting the route prefix (or group) inside the actual group method when we define it, followed by calling the closure, then cleaning up the prefix data so when we end the group method’s definition it doesn’t mess up other routes that aren’t set inside a group.

Now one problem most people would run into is how would one continuously call the group method for sub groups. Well the easiest approach is to have an array of string data and then append the group route to the array, call our closure, then pop off the last group route from the array. What this accomplishes is it allows us to continously add as many sub groups as we want because we’re constantly passing the current instance down the chain.

Accomplishing the same thing in Crystal Lang

So in order to accomplish the same thing in crystal language I needed to first figure out how to pass closures to methods as a parameter. Which actually turned out to be a bit easier than I expected despite the documentations being a bit confusing.

So first off when defining a block parameter you must use the &name syntax. Calling &name as a parameter tells the method or function that we’re going to be passing a block/closure. That’s the most basic example of a block in crystal. Which takes no parameters and returns no value. Inside the function or method that we define we would then need to call the call() definition on the block in order to execute it. You’d treat it like a class definition basically. So if you define any parameters you’d pass those parameters to the call definition in order to access that data inside the closure that you’re passing. Here’s that basic example of a no parameter block:

Simple right? Now how do we pass an empty closure to the example definition? Well you’d use the &-> {} syntax. It’s a definition short hand at it’s most basic form. So at first sight it doesn’t really look too appealing and probably a bit confusing. Now according to the documentation we can also use the do ... end syntax. Which is a lot cleaner, but the difference is the first shorthand syntax requires you to define the function argument types (if any) whilst the do ... end syntax just requires the names for parameters to access that data. Here’s an example of doing just that.

One thing I forgot to mention in my above example is how to define block parameters. The first example shows you the very bare bones example of passing an empty closure to a function. Now if you look at example2 above. You’ll notice a colon with a type after the closure/block name followed with a dart or arrow, which is required in order for it to work, and since there is no return type following the dart operator the return type is void. Although you can use an underscore to return “any” type.

Putting it all together

Now putting it all together to copy the slim framework 3 group routes system that I want to accomplish for my website.

(Note this is bare bones excluding controller#action’s code and what not. I basically just wanted to share with you how to chain the group calls together in a fashionable manner.)

Enjoy and I hope you learned something today 🙂