Chris, thans very much for the suggestion. I checked it, but there's the
issue of not knowing the number and the names of the variables beforehand.
Per the docs:
d = Dict{Symbol,Any}(:a=>5.0,:b=>2,:c=>"Hi!")
@materialize a, b, c = d
a == 5.0 #true
b == 2 #true
c == "Hi!" #true
This line here
@materialize a, b, c = d
is the issue - I do not know that I have a, b, and c. I only have access to
d; a, b and c are part of the template and they are interpolated in the
template's code. So this line would have to be dynamically generated again
by using keys(d) and maybe generating this as a string "@materialize a, b,
c = d" and eval'ing it. Which seems to only move my original problem
somewhere else?
Thanks,
Adrian
duminică, 14 august 2016, 18:17:51 UTC+2, Chris Rackauckas a scris:
>
> Any issues with @materialize? It seems like it does exactly what you're
> asking for...
>
> On Sunday, August 14, 2016 at 3:13:37 AM UTC-7, Adrian Salceanu 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?
>>
>>
>> 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.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>