Friday, December 19, 2008

templating dsl

So I am evaluating different ways of using my new "view adapter" templating engine. Sparing the details I would like to try out a few different versions of syntax. Straight php, s-expressions and then let/smalltalk.

$layout = Array('border_layout',
'center' => 'this is the center',
'south' => Array('border_layout',
'north' => 'this is the north of the south',
'south' => 'this is the south of the south'),
'north' => Array('form', 'method'=>'POST', 'with'=>Array(
Array('input', 'name'=>'first_name', 'label'=>'First Name'),
Array('submit', 'value'=>'Save')));

One nice thing about the php approach is that I can combine integer indexed with associative indexed arrays thus Array('submit', 'value' => 'Save') becomes possible as opposed to Array('type' => 'submit', 'value' => 'Save'). Clearly the adapter has to know that [0] is the type and thus shift that off before rendering the rest of the component.

$layout = [border_layout
center:'this is the center'
north:'this is the north of the south'
south:'this is the south of the south']
north:[form method:post with:[
[input name:first_name label:'First Name]
[submit value:Save]]];

As let sits atop php the same combination of integer indexed and associative indexes applies here too. Clearly replacing => with : and dropping quotes around single word keys and value makes things nicer as does making the commas optional as lists are white space seperated. As a note the reason I am dropping quotes is that within let there are no constants unless they are class constants. Thus there would never be a time you "accidentally" used a constant instead of a key. Also [] is not used for indexes or pushing values onto array in LET as it is more "smalltalk esque" in that you use methods for all things. And the reason I am not using [$var|$body] for code blocks is that I am using {$var|$body} as they are not used in smalltalk and coming from c/php { } feels right to me to denote a block of code.

$layout = (border_layout
(center 'this is the center')
(south (border_layout
(north 'this is the north of the south')
(south 'this is the south of the south'))
(north (form method:post with:(
(input name:first_name label:'First Name')
(submit value:Save))))

S-expressions will always have a certain element of "balance" about them not afforded by any other syntax, next to let I prefer this for sure. Except this is not strictly "lisp"y in that I am using key:value pairs intead of :key value or (key value) groupings.

$layout = {border_layout:{
center: 'this is the center',
south: {border_layout:{
north: 'this is the north of the south',
south: 'this is the south of the south'}},
north: {type:'form', method:'post', with:{
{type:'input', name:'first_name', label:'First Name'},
{type:'submit', value:'Save'}}};

Json is again consistent but there is no way of doing the {control, key:value} trick here except for maybe {submit:1, key:value} but that feels pretty hackish. Still at least you don't have to write Array() all over the place!

No comments: