On Sun, Aug 14, 2016 at 11:13 PM, Adrian Salceanu <[email protected]
> wrote:
> Thanks
>
> Maybe I wasn't clear enough - otherwise, can you please elaborate, I'm
> definitely still poking around, any clarifications would be highly
> appreciated.
>
> > creating a new module
> -> the module is available at compile time (the users of the templating
> system will place the vars in there, by convention).
>
Unless the user only do that once at compile time (i.e. the template is
only used once with no support of passing any template variables as
function arguments) than it is runtime and not compile time.
>
> > parse julia code
> -> it's not really parsing julia code, it has no meaning at the point.
> It's simply basic string processing and it's fast - tried with a 10K lines
> HTML file, no sweat.
>
It is, in `include_string()`
>
> > defining globals
> -> why are they globals? include_string() is used inside a function,
> inside a module within the app.
>
In the module, and `include_string()` reference those globals.
>
> > eval in a module
> -> true, but then what can we do? That's the way of doing metaprogramming
> in Julia, and it's widely used, isn't it?
>
Which should only be done at compile time, not runtime.
> I guess that would be the price for not having to do
> print("<html><head>...") like our ancestors used to in PHP or ASP, when not
> being chased by tigers (or something around that age).
>
>
> duminică, 14 august 2016, 15:01:47 UTC+2, Yichao Yu a scris:
>
>>
>>
>> On Sun, Aug 14, 2016 at 6:13 PM, Adrian Salceanu <[email protected]>
>> wrote:
>>
>>> Variables contained in a module and then parsed Julia code included
>>> within a function using include_string().
>>>
>>> Any obvious performance issues with this approach?
>>>
>>
>> Everything about it?
>> Literally every steps are hitting the slow path that is only meant to
>> execute at compile time and not runtime. Including
>>
>> Creating a new module, parse julia code, eval in a module, defining
>> globals.
>>
>>
>>>
>>>
>>> duminică, 14 august 2016, 12:11:06 UTC+2, Adrian Salceanu a scris:
>>>>
>>>> OK, actually, that's not nearly half as bad. Variables contained in a
>>>> module
>>>>
>>>> include("src/Ejl_str.jl")
>>>> using Ejl
>>>>
>>>>
>>>> module _
>>>> couñtry = "España"
>>>> lang = "en"
>>>> end
>>>>
>>>>
>>>> function render_template()
>>>> tpl_data = ejl"""
>>>> <% if _.lang == "en" :>
>>>> Hello from me, ...
>>>> <: else :>
>>>> Hola
>>>> <: end %>
>>>>
>>>>
>>>> %= _.couñtry == "España" ? "Olé" : "Aye"
>>>> moo
>>>> """
>>>>
>>>>
>>>> include_string(join(tpl_data, "\n"))
>>>> join(____output, "\n")
>>>> end
>>>>
>>>>
>>>> render_template() |> println
>>>>
>>>> Hello from me, ...
>>>>
>>>>
>>>> Olé
>>>> moo
>>>>
>>>>
>>>> duminică, 14 august 2016, 11:20:37 UTC+2, Adrian Salceanu a scris:
>>>>>
>>>>> Thanks
>>>>>
>>>>> Yes, I've thought about a few ways to mitigate some of these issues:
>>>>>
>>>>> 1. in the app I can setup a module (like Render) and evaluate into
>>>>> this module exclusively.
>>>>> Hence, another approach might be to have some helper methods that
>>>>> setup the variables in the module and then eval the template itself inside
>>>>> the module too (must try though). So something in the lines of:
>>>>> set(:foo, "foo")
>>>>> set(:bar, [1, 2, 3])
>>>>> parse_tpl(ejl"""$(foo) and $(bar)""")
>>>>> # all the above gets parsed in Render
>>>>>
>>>>> 2. break the parsing in 2 steps:
>>>>> a. reading the template string and parse it to generated Julia code
>>>>> (as strings) (an array of Julia code lines) - cache it
>>>>> b. (load strings from cache and) eval the code together with the vars
>>>>>
>>>>> ===
>>>>>
>>>>> Another approach (which is how it's done in one of the Ruby templating
>>>>> engine) is to generate a full function definition, whose body parses the
>>>>> template and takes the variables as params. And then eval and execute the
>>>>> function with its params. However, I'm still struggling with the
>>>>> metaprogramming API as for instance parse() chokes on multiple lines, and
>>>>> I
>>>>> couldn't find a functional equivalent of a quote ... end blocks. But I'm
>>>>> hoping include_string() will do the trick (must test though).
>>>>>
>>>>>
>>>>> sâmbătă, 13 august 2016, 15:20:01 UTC+2, Yichao Yu a scris:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Sat, Aug 13, 2016 at 8:06 PM, Adrian Salceanu <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> That's pretty difficult as my goal is to use embedded Julia as the
>>>>>>> templating language. Similar to Ruby's ERB, ex:
>>>>>>> http://www.stuartellis.eu/articles/erb/
>>>>>>>
>>>>>>> So say in the template I have something like
>>>>>>>
>>>>>>> <% if foo == "bar" %>
>>>>>>> Bar
>>>>>>> <% else %>
>>>>>>> Baz
>>>>>>> <% end %>
>>>>>>>
>>>>>>> The idea is to use Julia itself to parse the code block and Julia
>>>>>>> will raise an error is foo is not defined. So I can't really look it up.
>>>>>>>
>>>>>>
>>>>>> It's ok to use the julia syntax and parser but it's a pretty bad idea
>>>>>> to use the julia runtime to actually evaluating the expression, and
>>>>>> absolutely not by making them reference to local variables.
>>>>>>
>>>>>> For a start you are not allowed to reference local variables by names
>>>>>> anyway.
>>>>>> You also shouldn't allow reference to/overwrite of other local
>>>>>> variables (i.e. the template namespace should be fully isolated and
>>>>>> independent of any scope in the template engine).
>>>>>>
>>>>>> Since you want to eval, it seems that efficiency is not an issue, in
>>>>>> which case you can create an anonymous module and eval/create globals in
>>>>>> that module. This should also be reasonably fast if you are only using
>>>>>> the
>>>>>> template once.
>>>>>>
>>>>>> If you want to use it multiple time and compile the template, you
>>>>>> should then scan for variable references in the expressions and process
>>>>>> it
>>>>>> from there.
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> I can either do
>>>>>>>
>>>>>>> <% if _[:foo] == "bar" %>
>>>>>>>
>>>>>>> or
>>>>>>>
>>>>>>> <% if _(:foo) == "bar" %>
>>>>>>>
>>>>>>> but it's not that nice.
>>>>>>>
>>>>>>>
>>>>>>> sâmbătă, 13 august 2016, 13:24:18 UTC+2, Yichao Yu a scris:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Sat, Aug 13, 2016 at 7:13 PM, Adrian Salceanu <
>>>>>>>> [email protected]> wrote:
>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>>
>>>>>>>>> It's for a templating engine. The user creates the document (a
>>>>>>>>> string) which contains interpolated variables placeholders and
>>>>>>>>> markup. When
>>>>>>>>> the template is rendered, the placeholders must be replaced with the
>>>>>>>>> corresponding values from the dict.
>>>>>>>>>
>>>>>>>>> The lines in the template are eval-ed and so Julia will look for
>>>>>>>>> the variables in the scope. So the vars should be already defined.
>>>>>>>>>
>>>>>>>>
>>>>>>>> You should explicitly look up those variables in the dict instead.
>>>>>>>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Yes, ultimately I can force the user to use a dict (or rather a
>>>>>>>>> function for a bit of semantic sugar) - which is preferable from a
>>>>>>>>> performance perspective, but less pretty end error prone from the user
>>>>>>>>> perspective.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>