template engine [ was: Re: Implementing tables - advice wanted ]
Gaspar Chilingarov
nm@REDACTED
Wed Jun 14 13:48:24 CEST 2006
Joe Armstrong (AL/EAB) wrote:
> I see no reason why a template engine should offer any other than
> full access to all Erlang functions, not some ad-hock subset.
>
>
> My template engine is described here:
>
> http://www.erlang.org/ml-archive/erlang-questions/200602/msg00326.html
>
> I've edited some comments into Gaspar's mail at the end of this post.
>
> <? map
> Since this posting I have done one or two experiments - all failed
> so I stand by the original design.
>
> I also came up with a small (and useful) "mini template".
>
> Since it is instructive, I can relate what happened when I tried to
> improve upon the original design.
>
> - I made two attempts to "improve" my design
> 1) make a restricted template language (like velocity)
> 2) make something A lot like PHP
>
> What happened?
>
> 1)
>
> I did something like velocity - but I very soon missed
> the power of a full programming language - doing easy thing was,
> well .. uuug easy - doing other things was complex and doing
> difficult things was ... impossible.
>
> Embedding ajax calls using higher order functions - forget it ...
>
> I junked this experiment
>
> 2) I thought "this (ie my template engine) is pretty much like PHP
> let's make it even more like PHP to attract users who know PHP.
>
> To do this I added an out(String) primitive and changed the semantics of
> my
> template language.
>
> < aside >
> I have to briefly explain the semantics of my original template
> language:
>
> <h1>hello</h1>
> <? N = 10, "" ?>
> <p>Factorial <? N ?> is <? fac(N) ?>
>
> This means "create a string"
>
> "<h1>hello</h1> ++ "" ++ "<p>factorial N is" ++
> coerce_to_string(N) ++ " is " ++ ...
>
> is the LAST value is a <? .. ?> is coerced into a string and the value
> is
> pasted into the document. Bindings created *within* <? ... ?> get
> carried to the
> next <? ... ?> context.
> </aside>
>
> My new language (inspired by PHP) was more like this:
>
> <h1>hello</h1>
> <? N = 10 ?>
> <p>factorial <? out(N) ?> is <? out(fac(N)) ?>
>
> Which was transformed into:
>
> out("<h1>hello</h1>"),
> N = 10,
> out("<p>factorial ");
> out(N),
> out(" is "),
> out(fac(N))
>
> At the time I rather liked this - all I had to do was enclose
> top level bits of HTML in an out(...) wrapper.
>
> Then my subroutines could also call out(...) - like PHP
>
> This resulted in a soggy mess. Why? - evaluation order now matters.
> I/O is an imperative side effect, scattering out(X) statements at random
>
> in subroutines implies that somehow and somewhere you have an idea as to
>
> in which order these subroutines will be called.
>
> Pure functional programming is far easier - in the earlier model
> each function returns a string (if that's what you want) and the caller
> assembles the
> return values into new strings. The order of calling the routines is
> irrelevant,
> since you will always get the same result.
>
> I/O by side effects (using out(X) in a subroutines) made writing all
> other than simple code a mess.
>
> I junked this experiment.
>
> To recap - If I had distributed experiment 1 (the velocity approach) I
> would
> have committed a venial sin, resulting in "temporary loss of grace" from
> the
> Erlang Users. But distributing something with a PHP like syntax would be
> a mortal
> sin requiring a valid confession in articolo mortis - and what would
> happen if
> I met an untimely end, like in a car crash, so that I couldn't confess
> ...
>
> So we're back to my original design.
>
> In passing I did make a little mini-mini-template language.
>
> This is simply HTML with a few ${Var} variables in it - like this:
>
> Put this in a file foo.template
>
> <title>${title}</title>
> <h1>hello ${person} how are you?
>
>
> Then expand with:
>
> expand:file("foo.template", [{"title", "my web page"},
> {"person", "joe"}]).
>
> Or make an xml template instance (say in the file bar)
>
> <title>my web page</title>
> <person>joe</person>
>
> and expand with:
>
> expand_xml("bar!", "foo.template")
>
> This mini-mini-template language which is laughably simple,
> is *very useful*.
>
>
> /Joe
>
>
>
>
>
>> -----Original Message-----
>> From: owner-erlang-questions@REDACTED
>> [mailto:owner-erlang-questions@REDACTED] On Behalf Of
>> Gaspar Chilingarov
>> Sent: den 13 juni 2006 23:23
>> To: Erlang Users' List; ke han
>> Subject: RFC: template engine [ was: Re: Implementing tables
>> - advice wanted ]
>>
>> Hello all!
>>
>> Post directed mainly to ke han, but all other list members are welcome
>> -- You have mentioned html template engine for erlang - what
>> kind of features do you like in there ?
>>
>> For current moment I got some simple engine which provides
>> following templating commands -
>>
>> <%TRANSLATE atom%> - generate string, calling some
>> translation function (to make multilangual sites)
>>
>
> <? translate(atom) ?>
>
>> <%FOREACH keyname%> - <%/FOREACH%> - take element keyname
>> from proplist (which should have list value) and iterate
>> inner part of FOREACH loop for each element in that list.
>
> <? map(fun foo/1, L) ?> with an external function, or
>
> <? map(fun(I) ->
> ["<h1> ...", I , ... ]
> end, L) ?>
>
>
>> <%WITH keyname%> <%/WITH%>- just go one level deeper - fetch
>> one element from proplist and execute inner template with it
>
> I don't understand - possibly
>
> <? someFunc(dict:lookup(keyname, D)) ?>
>
>
>> <%PUT keyname%> - just put element of proplist into current position.
>
> <? D1 = dict:store(keyname, Val, D), "" ?> (note the extra "" :-)
>
>> <%PUTVALUE%> - if we are in a leaf node - put it's value into
>> current position - ether string or integer.
>
> ??????
>
>> so
>> if you have template
>> <%FOREACH args%><%PUTVALUE%> <%/FOREACH%>
>>
>> and we feed templating function with
>> {struct, [
>> {args, {array, ["Hello", "world", "!"]} } ]} data we
>> will receive "Hello world ! " string.
>>
>> this approach - added with if/ifdef/else commands allows
>> create templates which are totally separate from programming
>> language and are driven only by data which is fed to template
>> interpreted.
>>
>> it somehow resembles XSLT, but much more simple to allow HTML
>> designers easily use it and put into pages without disturbing
>> programmer too much.
>>
>> second idea with such markup is that there is translator from
>> such markup to JSON notation, and there is JS template
>> renderer, which could be run on client machine - thus
>> allowing passing from server not rendered template, but
>> parsed template and data -- JS copes well even on slow
>> machines with datasets about up to 1000 elements - like
>> 10x100 table - which is practically enough for most tasks.
>>
>>
>> solution, which you would like to see - even too fantastic or
>> futuristic -- because it's always possible to find something
>> reasonable and practical there.
>>
>
>
>> Looking forward for answers :)
>>
>> --
>> Gaspar Chilingarov
>>
>> System Administrator,
>> Network security consulting
>>
>> t +37493 419763 (mob)
>> i 63174784
>> e nm@REDACTED
>>
>
--
Gaspar Chilingarov
System Administrator,
Network security consulting
t +37493 419763 (mob)
i 63174784
e nm@REDACTED
More information about the erlang-questions
mailing list