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