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

Right. So if I execute "eval()" and "include_string()" within a module 
other than Main (currently doing this into a dedicated Render module) would 
that be ok? 

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