On Sun, Aug 14, 2016 at 11:33 PM, Adrian Salceanu <adrian.salce...@gmail.com
> wrote:

> Huhm... so re
>
> > defining globals
>
> According to the API docs:
>
> *include_string**(code::AbstractString**[**, filename**]**)*
>
> Like include, except reads code from the given string rather than from a
> file. Since there is no file path involved, no path processing or fetching
> from node 1 is done.
>
>
> But then I think you're right, the code is included / eval'd in Main - so
> it's not really like include(), which provides for mixin behavior? :-O
>
>
Not sure what do you mean by `mixin`. all of `include_string`, `eval` and
`include` works in the scope of current module, none of them will see
anything in the scope of the function that calls them.


> duminică, 14 august 2016, 17:13:28 UTC+2, Adrian Salceanu a scris:
>>
>> 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).
>>
>> > 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.
>>
>> > defining globals
>> -> why are they globals? include_string() is used inside a function,
>> inside a module within the app.
>>
>> > 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?
>> 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 <adrian....@gmail.com>
>>> 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 <
>>>>>>> adrian....@gmail.com> 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 <
>>>>>>>>> adrian....@gmail.com> 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