Thank you very much Yichao

I'm afraid then that I don't fully understand the consequences of all the 
steps in this workflow. Let me see if I get things right (sorry if some of 
my questions are dumb or seem obvious and thanks for your patience). 

> 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.

I was thinking about having the module itself defined in the controller for 
example (or some other standalone .jl source file), completely outside the 
templating engine itself, and then referencing the variables defined within 
this module. Are you saying that in this case, the module itself would not 
be compiled? 

> It is, in `include_string()`
Ah sure. We're on the same page here, with the only exception that by 
"parse" I was referring to the parsing phase of the template (converting 
the special template markup) and considered "include_string()" more as a 
part of rendering the template (eval'ing the julia code together with the 
vars to generate the HTML code). 

> In the module, and `include_string()` reference those globals.

If I have 

module TplVars
  const var1 = "foo"
  const var2 = "bar"
  const var3 = 42
end

and then from the template file I reference them

ejl"""
<html>... 
  <p>
    $(TplVars.var1)
  </p>
</html>
"""

would that still be in the global scope? 


luni, 15 august 2016, 16:23:37 UTC+2, Yichao Yu a scris:
>
>
>
> On Sun, Aug 14, 2016 at 11:13 PM, Adrian Salceanu <[email protected] 
> <javascript:>> 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.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>
>

Reply via email to