I can understand that if you're used to building interfaces that use R's non-standard evaluation and reified environments heavily, it can be frustrating to not have those features. But I don't think that means that you cannot build convenient and safe interfaces for data analysis.
On Fri, Jul 24, 2015 at 11:48 AM, Brandon Taylor < brandon.taylor...@gmail.com> wrote: > Ok, maybe I was being harsh when I used the word mis-marketing. The post > here: http://julialang.org/blog/2012/02/why-we-created-julia/ > specifically mentions that one of Julia's goals is to be as easy for > statistics as R. Building a domain specific language is more difficult (but > clearly not impossible) without environment access. Again, the examples I'm > most familiar with are in the Hadleyverse (see previous posts in this > thread for links to vignettes). Also, this is probably the fifth time that > me being stubborn seems to have caused tensions on threads, and I'm sorry > for that. Learning a bit about C compilers convinced me that I was > completely wrong about environments needing to be implemented for scoping > to work. > > > On Friday, July 24, 2015 at 3:46:28 AM UTC-4, Milan Bouchet-Valat wrote: > >> Le jeudi 23 juillet 2015 à 15:31 -0700, Brandon Taylor a écrit : >> > I'm not saying inherent slowness will be particularly useful. I'm >> > saying environment access will be particularly useful. The point of >> > Julia is no compromise between speed and code-ability. If it is not >> > possible to integrate environment access and speed, then I think that >> > Julia is mis-marketing itself, at least as a viable R alternative. >> Could you give us a concrete example of what you would like to do with >> environments? I haven't encountered cases where I would personally miss >> this R feature in Julia, so I don't understand what you're trying to >> achieve. >> >> Also, note that when we say that a solution will be slow in Julia, it >> doesn't mean that it would be slower than in R. It's just that to write >> code approximately equivalent to C, you cannot use the same solutions >> as R. >> >> >> Regards >> >> >> > On Friday, July 24, 2015 at 12:35:13 AM UTC+4, Yichao Yu wrote: >> > > On Thu, Jul 23, 2015 at 4:23 PM, Brandon Taylor >> > > <brandon....@gmail.com> wrote: >> > > > Will it cause a slowdown because there is a better way to do it >> > > or will it >> > > > cause a slowdown because something inherent about environment >> > > access? >> > > > Because if the second is the case, then it would be worth it, at >> > > least to >> > > > me. >> > > >> > > AFAICT, environment access is basically global variable and it will >> > > trash any optimization julia can do so in some sense the slow down >> > > is >> > > inherent about environment access. >> > > >> > > I don't see why the inherent slowness would be particularly useful >> > > though. >> > > >> > > > >> > > > On Thursday, July 23, 2015 at 11:13:14 AM UTC+8, Yichao Yu wrote: >> > > >> >> > > >> On Wed, Jul 22, 2015 at 10:51 PM, Brandon Taylor >> > > >> <brandon....@gmail.com> wrote: >> > > >> > Ok, made some progress. Still having trouble with a _ENV_ not >> > > defined >> > > >> > error: >> > > >> > how could it not be defined if it's a global variable??? >> > > Figuring out >> > > >> > argument passing is going to be tricky. Is this kind of system >> > > feasible >> > > >> > or >> > > >> > is it going to cause huge slowdowns? >> > > >> >> > > >> It'll cause a huge slowdown. >> > > >> >> > > >> > >> > > >> > using DataFrames >> > > >> > >> > > >> > import Base.convert >> > > >> > >> > > >> > _TYPES_ = Symbol[] >> > > >> > >> > > >> > type _LAZY_ >> > > >> > _E_::Expr >> > > >> > _ENV_::Symbol >> > > >> > end >> > > >> > >> > > >> > # modify dicts such that if a key is not found, search the >> > > parent >> > > >> > function Base.getindex{K,V}(h::Dict{K,V}, key) >> > > >> > index = Base.ht_keyindex(h, key) >> > > >> > if index < 0 >> > > >> > if :_parent in keys(h) >> > > >> > Base.getindex(eval(h[:_parent]), key) >> > > >> > else >> > > >> > throw(KeyError(key)) >> > > >> > end >> > > >> > else >> > > >> > h.vals[index]::V >> > > >> > end >> > > >> > end >> > > >> > >> > > >> > # allow inheritance from modules >> > > >> > function convert(::Type{Dict}, m::Module) >> > > >> > dict = Dict() >> > > >> > for name in names(m) >> > > >> > dict[name] = eval( :(Base.$name) ) >> > > >> > # add types to type list >> > > >> > if typeof(dict[name]) <: DataType >> > > >> > push!(_TYPES_, name) >> > > >> > end >> > > >> > end >> > > >> > dict >> > > >> > end >> > > >> > >> > > >> > # allow inheritance from DataFrames >> > > >> > function convert(::Type{Dict}, d::DataFrame) >> > > >> > dict = Dict() >> > > >> > for name in names(d) >> > > >> > dict[name] = d[name] >> > > >> > # add types to type list >> > > >> > if typeof(dict[name]) <: DataType >> > > >> > push!(_TYPES_, name) >> > > >> > end >> > > >> > end >> > > >> > dict >> > > >> > end >> > > >> > >> > > >> > # establish the base environment, save it as global, and point >> > > it to an >> > > >> > empty dictionary >> > > >> > macro _ENV_MACRO_() >> > > >> > esc(quote >> > > >> > _ENV_ = gensym() >> > > >> > _GLOBAL_ = _ENV_ >> > > >> > eval(quote >> > > >> > $_ENV_ = Dict() >> > > >> > end) >> > > >> > end) >> > > >> > end >> > > >> > >> > > >> > # establish a new environment and point it towards a dict >> > > daughter of >> > > >> > the >> > > >> > old environment >> > > >> > macro _NEW_ENV_MACRO_() >> > > >> > esc(quote >> > > >> > _NEW_ENV_ = gensym() >> > > >> > eval(quote >> > > >> > $_NEW_ENV_ = {:_parent => $(Expr(:quote, _ENV_)) } >> > > >> > end) >> > > >> > _ENV_ = _NEW_ENV_ >> > > >> > end) >> > > >> > end >> > > >> > >> > > >> > # establish a new environment and point it towards a dict >> > > daughter of >> > > >> > the >> > > >> > old environment with dict contents >> > > >> > macro _ADD_ENV_MACRO_(dict) >> > > >> > esc(quote >> > > >> > _DICT_ = $dict >> > > >> > _ADD_ENV_ = gensym() >> > > >> > eval(quote >> > > >> > $_ADD_ENV_ = convert(Dict, $_DICT_) >> > > >> > $_ADD_ENV_[:_parent] = $(Expr(:quote, _ENV_)) >> > > >> > end) >> > > >> > _ENV_ = _ADD_ENV_ >> > > >> > end) >> > > >> > end >> > > >> > >> > > >> > # jump back in time to the previous generation >> > > >> > macro _REMOVE_ENV_MACRO_() >> > > >> > esc(quote >> > > >> > _ENV_ = eval(_ENV_)[:_parent] >> > > >> > end) >> > > >> > end >> > > >> > >> > > >> > >> > > >> > # new types will have to be included in a module at the >> > > beginning of >> > > >> > code >> > > >> > # that module will need to be converted to a Dict along with >> > > base >> > > >> > # a namespace will need to be created such that module dicts >> > > inherit >> > > >> > from >> > > >> > each other, with base at the top >> > > >> > >> > > >> > @_ENV_MACRO_() >> > > >> > @_ADD_ENV_MACRO_(Base) >> > > >> > @_NEW_ENV_MACRO_ >> > > >> > >> > > >> > # test expression >> > > >> > e = >> > > >> > quote >> > > >> > a = 1 >> > > >> > b = 2 >> > > >> > test = function() >> > > >> > b = a >> > > >> > end >> > > >> > end >> > > >> > >> > > >> > >> > > >> > # reformat code to use dict scoping >> > > >> > function _ENV_REPLACE_(_Lazy_::_LAZY_) >> > > >> > >> > > >> > e = copy(_Lazy_._E_) >> > > >> > _ENV_ = _Lazy_._ENV_ >> > > >> > >> > > >> > # expressions wrapped in _esc will be left alone >> > > >> > if length(e.args) > 0 >> > > >> > if (e.head == :call) & (e.args[1] == :_esc) >> > > >> > return e.args[2] >> > > >> > end >> > > >> > end >> > > >> > >> > > >> > # set a new scope for a new function. This will also have to >> > > be done >> > > >> > with >> > > >> > for loops, modules, etc. >> > > >> > if (e.head == :function) >> > > >> > # insert a new scope definition into the function >> > > definition >> > > >> > e.args[2].args = [ >> > > >> > e.args[2].args[1], >> > > >> > :(@_NEW_ENV_MACRO_), >> > > >> > :(_ENV_REPLACE!_( >> > > >> > $(Expr(:block, >> > > >> > e.args[2].args[2:end]...)))), >> > > >> > :(@_REMOVE_ENV_MACRO_)] >> > > >> > >> > > >> > # ignore line numbers >> > > >> > elseif e.head != :line >> > > >> > # for each sentence >> > > >> > for i in 1:length(e.args) >> > > >> > # replace symbols with their dict scoped version >> > > >> > if typeof(e.args[i]) == Symbol >> > > >> > >> > > >> > #avoid types >> > > >> > if !(e.args[i] in _TYPES_) >> > > >> > e.args[i] = :($_ENV_[$(string(e.args[i]))]) >> > > >> > end >> > > >> > >> > > >> > # recur into new expressions >> > > >> > elseif typeof(e.args[i]) == Expr >> > > >> > e.args[i] = _ENV_REPLACE!_(e.args[i], _ENV_) >> > > >> > end >> > > >> > end >> > > >> > end >> > > >> > e >> > > >> > end >> > > >> > >> > > >> > function _LAZY_(e::Expr) >> > > >> > _LAZY_(e, _ENV_) >> > > >> > end >> > > >> > >> > > >> > macro _LAZY_EVAL_(_Lazy_) >> > > >> > esc(quote >> > > >> > eval(_ENV_REPLACE_($_Lazy_)) >> > > >> > end) >> > > >> > end >> > > >> > >> > > >> > >> > > >> > @_LAZY_EVAL_(_LAZY_(e)) >> > > >> > >> > > >> > eval(_ENV_)["a"] >> > > >> > eval(_ENV_)["b"] >> > > >> > eval(_ENV_)["test"]() ## ERROR HERE >> > > >> > >> > > >> > >> > > >> > >> > > >> > >> > > >> > >> > > >> > On Wednesday, July 22, 2015 at 11:30:10 AM UTC+8, Brandon >> > > Taylor wrote: >> > > >> >> >> > > >> >> More to do: >> > > >> >> Expressions would also have to be escaped from quoting. >> > > >> >> If we can't scope types within dicts, it might be necessary >> > > to have >> > > >> >> special markers for types so they can avoid being scoped. >> > > >> >> I don't think that macros will be necessary anymore >> > > >> >> >> > > >> >> >> > > >> >> On Wednesday, July 22, 2015 at 11:14:38 AM UTC+8, Brandon >> > > Taylor wrote: >> > > >> >>> >> > > >> >>> Ok so I've got a good start. I bet John Myles White didn't >> > > think I >> > > >> >>> could >> > > >> >>> get this far. Anyway, I'm getting caught up in defining my >> > > own escape >> > > >> >>> function. I'm getting lost in multiple layers of meta. >> > > >> >>> >> > > >> >>> using DataFrames >> > > >> >>> >> > > >> >>> import Base.convert >> > > >> >>> >> > > >> >>> # allow inheritance from modules >> > > >> >>> function convert(::Type{Dict}, m::Module) >> > > >> >>> dict = Dict() >> > > >> >>> for name in names(m) >> > > >> >>> dict[name] = eval( :(Base.$name) ) >> > > >> >>> end >> > > >> >>> dict >> > > >> >>> end >> > > >> >>> >> > > >> >>> base_dict = convert(Dict, Base) >> > > >> >>> >> > > >> >>> # allow inheritance from DataFrames >> > > >> >>> function convert(::Type{Dict}, d::DataFrame) >> > > >> >>> dict = Dict() >> > > >> >>> for name in names(d) >> > > >> >>> dict[name] = d[name] >> > > >> >>> end >> > > >> >>> dict >> > > >> >>> end >> > > >> >>> >> > > >> >>> # modify dicts such that if a key is not found, search the >> > > parent >> > > >> >>> function Base.getindex{K,V}(h::Dict{K,V}, key) >> > > >> >>> index = Base.ht_keyindex(h, key) >> > > >> >>> if index < 0 >> > > >> >>> if :_parent in keys(h) >> > > >> >>> Base.getindex(h[:_parent], key) >> > > >> >>> else >> > > >> >>> throw(KeyError(key)) >> > > >> >>> end >> > > >> >>> else >> > > >> >>> h.vals[index]::V >> > > >> >>> end >> > > >> >>> end >> > > >> >>> >> > > >> >>> # test expression >> > > >> >>> e = >> > > >> >>> quote >> > > >> >>> a = 1 >> > > >> >>> # anonymous functions required for proper scoping >> > > >> >>> test = function() >> > > >> >>> b = a >> > > >> >>> end >> > > >> >>> end >> > > >> >>> >> > > >> >>> # set up the global environment >> > > >> >>> _env = gensym() >> > > >> >>> eval(:($_env = [:_parent => base_dict] ) ) >> > > >> >>> >> > > >> >>> >> > > >> >>> #_new_env = _env >> > > >> >>> # this is the code that needs to be escaped >> > > >> >>> #eval(:($_new_env = [:_parent => eval(_env)] ) ) >> > > >> >>> >> > > >> >>> # reformat code to use dict scoping >> > > >> >>> function env_replace!(e::Expr, >> > > >> >>> _env::Symbol = _env) >> > > >> >>> >> > > >> >>> # expressions wrapped in _esc will be left alone >> > > >> >>> if length(e.args) > 0 >> > > >> >>> if (e.head == :call) & (e.args[1] == :_esc) >> > > >> >>> return e.args[2] >> > > >> >>> end >> > > >> >>> end >> > > >> >>> >> > > >> >>> # set a new scope for a new function. This will also have >> > > to be done >> > > >> >>> with for loops, modules, etc. >> > > >> >>> if (e.head == :function) >> > > >> >>> # insert a new scope definition into the function >> > > definition >> > > >> >>> _new_env = gensym() >> > > >> >>> e.args[2].args = [ >> > > >> >>> e.args[2].args[1], >> > > >> >>> :_esc(), #### need help here ### >> > > >> >>> e.args[2].args[2:end] ] >> > > >> >>> _env = _new_env >> > > >> >>> end >> > > >> >>> >> > > >> >>> # ignore line numbers >> > > >> >>> if e.head != :line >> > > >> >>> >> > > >> >>> for i in 1:length(e.args) >> > > >> >>> # replace symbols with their dict scoped version >> > > >> >>> if typeof(e.args[i]) == Symbol >> > > >> >>> e.args[i] = :($_env[$(string(e.args[i]))]) >> > > >> >>> >> > > >> >>> # recur into new expressions >> > > >> >>> elseif typeof(e.args[i]) == Expr >> > > >> >>> e.args[i] = env_replace!(e.args[i], _env) >> > > >> >>> end >> > > >> >>> end >> > > >> >>> end >> > > >> >>> e >> > > >> >>> end >> > > >> >>> >> > > >> >>> # here is an eval that allows evaluation within a certain >> > > dict scope >> > > >> >>> function lazy_eval(e::Expr, >> > > >> >>> _env::Symbol = _env) >> > > >> >>> eval(env_replace!(e), _env) >> > > >> >>> end >> > > >> >>> >> > > >> >>> >> > > >> >>> ## TO DO >> > > >> >>> # fix _esc problem >> > > >> >>> # prevent environment symbols from being scoped (perhaps >> > > with a >> > > >> >>> special >> > > >> >>> marker) >> > > >> >>> # rescope for, while, try, catch, finally, let, and type >> > > >> >>> # perhaps use fast anonymous to avoid performance slowdowns? >> > > >> >>> >> > > >> >>> >> > > >> >>> On Tuesday, July 21, 2015 at 10:10:58 AM UTC+8, Brandon >> > > Taylor wrote: >> > > >> >>>> >> > > >> >>>> And there would need to be a special marker for them, such >> > > that if >> > > >> >>>> I'm >> > > >> >>>> in function f, f[:a] won't get preprocessed as f[:f][:a] >> > > >> >>>> >> > > >> >>>> On Tuesday, July 21, 2015 at 10:03:08 AM UTC+8, Brandon >> > > Taylor wrote: >> > > >> >>>>> >> > > >> >>>>> Although that would probably require nested dicts. Each >> > > would have a >> > > >> >>>>> parent dict, and if a lookup isn't found in the current >> > > dict, the >> > > >> >>>>> parent >> > > >> >>>>> dict would be searched. >> > > >> >>>>> >> > > >> >>>>> On Tuesday, July 21, 2015 at 9:53:50 AM UTC+8, Brandon >> > > Taylor wrote: >> > > >> >>>>>> >> > > >> >>>>>> I should be possible to preprocess code such that >> > > everything is put >> > > >> >>>>>> into a dict based on the name of enclosing function (and >> > > global >> > > >> >>>>>> variables >> > > >> >>>>>> will just go into a dict called global). >> > > >> >>>>>> >> > > >> >>>>>> On Tuesday, July 21, 2015 at 9:42:00 AM UTC+8, Brandon >> > > Taylor >> > > >> >>>>>> wrote: >> > > >> >>>>>>> >> > > >> >>>>>>> Dicts seem to work pretty well for this kind of thing. >> > > >> >>>>>>> >> > > >> >>>>>>> On Tuesday, July 21, 2015 at 9:38:36 AM UTC+8, Brandon >> > > Taylor >> > > >> >>>>>>> wrote: >> > > >> >>>>>>>> >> > > >> >>>>>>>> I'm getting a cannot assign variables in other modules >> > > error. >> > > >> >>>>>>>> >> > > >> >>>>>>>> On Tuesday, July 21, 2015 at 6:39:44 AM UTC+8, Yichao >> > > Yu wrote: >> > > >> >>>>>>>>> >> > > >> >>>>>>>>> On Mon, Jul 20, 2015 at 6:35 PM, Brandon Taylor >> > > >> >>>>>>>>> <brandon....@gmail.com> wrote: >> > > >> >>>>>>>>> > Ok, a thought, Julia has an inbuilt idea of a >> > > module. Would it >> > > >> >>>>>>>>> > be >> > > >> >>>>>>>>> > possible >> > > >> >>>>>>>>> > to hijack this functionality to provide pseudo >> > > -environments? >> > > >> >>>>>>>>> > That >> > > >> >>>>>>>>> > is, never >> > > >> >>>>>>>>> > referring to anything that is not already in an >> > > explicit >> > > >> >>>>>>>>> > module? >> > > >> >>>>>>>>> > And also, >> > > >> >>>>>>>>> > have a data-frame simply be a module? >> > > >> >>>>>>>>> >> > > >> >>>>>>>>> I think this would in principle works. A module is >> > > basically >> > > >> >>>>>>>>> what >> > > >> >>>>>>>>> global scope means so all the performance concern >> > > applies. >> > > >> >>>>>>>>> >> > > >> >>>>>>>>> > >> > > >> >>>>>>>>> > >> > > >> >>>>>>>>> > On Friday, July 10, 2015 at 11:31:36 PM UTC+8, >> > > Brandon Taylor >> > > >> >>>>>>>>> > wrote: >> > > >> >>>>>>>>> >> >> > > >> >>>>>>>>> >> I don't know if you came across the vignette? >> > > >> >>>>>>>>> >> >> > > >> >>>>>>>>> >> >> > > >> >>>>>>>>> >> http://cran.r-project.org/web/packages/lazyeval/vig >> > > nettes/lazyeval.html ? >> > > >> >>>>>>>>> >> dplyr uses lazyeval extensively, see >> > > >> >>>>>>>>> >> >> > > >> >>>>>>>>> >> >> > > http://cran.r-project.org/web/packages/dplyr/vignettes/nse.html >> > > >> >>>>>>>>> >> . The cool >> > > >> >>>>>>>>> >> thing about being able to incorporate this kind of >> > > thing in >> > > >> >>>>>>>>> >> Julia would be >> > > >> >>>>>>>>> >> being able to use the self-reflection capabilities. >> > > >> >>>>>>>>> >> >> > > >> >>>>>>>>> >> On Friday, July 10, 2015 at 10:57:16 AM UTC-4, >> > > Cedric St-Jean >> > > >> >>>>>>>>> >> wrote: >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> On Thursday, July 9, 2015 at 10:35:30 PM UTC-4, >> > > Brandon >> > > >> >>>>>>>>> >>> Taylor >> > > >> >>>>>>>>> >>> wrote: >> > > >> >>>>>>>>> >>>> >> > > >> >>>>>>>>> >>>> To walk back in time, you could say something >> > > like: compile >> > > >> >>>>>>>>> >>>> this like >> > > >> >>>>>>>>> >>>> this was is in line 8. Or compile this like this >> > > was in >> > > >> >>>>>>>>> >>>> line >> > > >> >>>>>>>>> >>>> 5. It seems >> > > >> >>>>>>>>> >>>> like Julia already has some of this functionality >> > > in >> > > >> >>>>>>>>> >>>> macros. >> > > >> >>>>>>>>> >>>> Internal >> > > >> >>>>>>>>> >>>> variables are compiled as if they were in local >> > > scope. But >> > > >> >>>>>>>>> >>>> escaped >> > > >> >>>>>>>>> >>>> expressions are compiled as if they were in >> > > global scope. >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> Could you provide context or a real-world use? >> > > I've looked >> > > >> >>>>>>>>> >>> at >> > > >> >>>>>>>>> >>> the >> > > >> >>>>>>>>> >>> lazyeval package, and I'm not entirely sure what >> > > it does. >> > > >> >>>>>>>>> >>> Does >> > > >> >>>>>>>>> >>> it provide >> > > >> >>>>>>>>> >>> lazy evaluation for R? That's easy to achieve in >> > > Julia >> > > >> >>>>>>>>> >>> (well, >> > > >> >>>>>>>>> >>> sorta). >> > > >> >>>>>>>>> >>> Instead of >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> d = determinant(matrix) >> > > >> >>>>>>>>> >>> .... >> > > >> >>>>>>>>> >>> u = 2 * d >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> you can write >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> d = ()->determinant(matrix) >> > > >> >>>>>>>>> >>> .... >> > > >> >>>>>>>>> >>> u = 2 * d() # determinant is evaluated on use, in >> > > the >> > > >> >>>>>>>>> >>> context >> > > >> >>>>>>>>> >>> where it >> > > >> >>>>>>>>> >>> was originally defined >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> With macros this can turn into >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> d = lazy(determinant(matrix)) >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> which looks nicer (and also can avoid computing >> > > the >> > > >> >>>>>>>>> >>> determinant >> > > >> >>>>>>>>> >>> twice if >> > > >> >>>>>>>>> >>> d() is called twice). >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>> Cédric >> > > >> >>>>>>>>> >>> >> > > >> >>>>>>>>> >>>> >> > > >> >>>>>>>>> >>>> >> > > >> >>>>>>>>> >>>> On Thursday, July 9, 2015 at 9:11:05 PM UTC-4, >> > > Cedric >> > > >> >>>>>>>>> >>>> St-Jean >> > > >> >>>>>>>>> >>>> wrote: >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> On Thursday, July 9, 2015 at 4:14:32 PM UTC-4, >> > > Brandon >> > > >> >>>>>>>>> >>>>> Taylor >> > > >> >>>>>>>>> >>>>> wrote: >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> Ok, here's where I'm getting hung up. You said >> > > that the >> > > >> >>>>>>>>> >>>>>> compiler >> > > >> >>>>>>>>> >>>>>> figures out the creation/lifetime of all >> > > variables at >> > > >> >>>>>>>>> >>>>>> compile time. So does >> > > >> >>>>>>>>> >>>>>> that mean there's a list like: >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> a maps to location 0 and exists from line 3 to >> > > line 9 >> > > >> >>>>>>>>> >>>>>> b maps to location 1 and exists from line 7 to >> > > line 9 >> > > >> >>>>>>>>> >>>>>> a maps to location 10 and exists from line 7 to >> > > 9? >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> and that to map variables to locations on any >> > > particular >> > > >> >>>>>>>>> >>>>>> line, the >> > > >> >>>>>>>>> >>>>>> compiler works its way up the list, >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> Yes, more or less. >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> This is perhaps even more helpful than the >> > > environment. >> > > >> >>>>>>>>> >>>>>> The >> > > >> >>>>>>>>> >>>>>> environment is immediately and completely >> > > determinable at >> > > >> >>>>>>>>> >>>>>> any point in the >> > > >> >>>>>>>>> >>>>>> program. This could make it possible to walk >> > > back in time >> > > >> >>>>>>>>> >>>>>> even within the >> > > >> >>>>>>>>> >>>>>> same scope. >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> Could you expand on what you're thinking of? >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> This kind of compile-time environment could >> > > conceivably be >> > > >> >>>>>>>>> >>>>> exposed to >> > > >> >>>>>>>>> >>>>> macros. Common Lisp had proposals along that >> > > line >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> ( >> > > https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node102.html) >> > > >> >>>>>>>>> >>>>> but as far as >> > > >> >>>>>>>>> >>>>> I can tell, it was too complicated and not >> > > useful enough, >> > > >> >>>>>>>>> >>>>> so >> > > >> >>>>>>>>> >>>>> it was >> > > >> >>>>>>>>> >>>>> axed/neutered at some point in the >> > > standardization >> > > >> >>>>>>>>> >>>>> process. >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> > Hadley Wickham's lazyeval package in R is >> > > pretty cool in >> > > >> >>>>>>>>> >>>>> > that you can >> > > >> >>>>>>>>> >>>>> > attach an environment to an expression, pass >> > > it in and >> > > >> >>>>>>>>> >>>>> > out >> > > >> >>>>>>>>> >>>>> > of functions with >> > > >> >>>>>>>>> >>>>> > various modifications, and then evaluate the >> > > expression >> > > >> >>>>>>>>> >>>>> > within the original >> > > >> >>>>>>>>> >>>>> > environment >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>> I don't know about R, but to me that sounds >> > > entirely >> > > >> >>>>>>>>> >>>>> doable >> > > >> >>>>>>>>> >>>>> with >> > > >> >>>>>>>>> >>>>> closures (and macros will give you a nice syntax >> > > for it) >> > > >> >>>>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>> On Wednesday, July 8, 2015 at 8:31:44 PM UTC-4, >> > > Yichao Yu >> > > >> >>>>>>>>> >>>>>> wrote: >> > > >> >>>>>>>>> >>>>>>> >> > > >> >>>>>>>>> >>>>>>> On Wed, Jul 8, 2015 at 8:23 PM, Yichao Yu >> > > >> >>>>>>>>> >>>>>>> <yyc...@gmail.com> wrote: >> > > >> >>>>>>>>> >>>>>>> > On Wed, Jul 8, 2015 at 7:48 PM, Brandon >> > > Taylor >> > > >> >>>>>>>>> >>>>>>> > <brandon....@gmail.com> wrote: >> > > >> >>>>>>>>> >>>>>>> >> Hmm, maybe I'm confused about compilation >> > > vs >> > > >> >>>>>>>>> >>>>>>> >> interpretation. Let >> > > >> >>>>>>>>> >>>>>>> >> me >> > > >> >>>>>>>>> >>>>>>> >> rephrase. Regardless of a how or when >> > > statement is >> > > >> >>>>>>>>> >>>>>>> >> evaluated, it >> > > >> >>>>>>>>> >>>>>>> >> must have >> > > >> >>>>>>>>> >>>>>>> >> access at least to its parent environments >> > > to >> > > >> >>>>>>>>> >>>>>>> >> successfully resolve >> > > >> >>>>>>>>> >>>>>>> >> a symbol. >> > > >> >>>>>>>>> >>>>>>> >> > > >> >>>>>>>>> >>>>>>> AFAIK, the only scope you can dynamically add >> > > variable >> > > >> >>>>>>>>> >>>>>>> to >> > > >> >>>>>>>>> >>>>>>> is the >> > > >> >>>>>>>>> >>>>>>> global scope. (This can be done with the >> > > `global` >> > > >> >>>>>>>>> >>>>>>> keyword >> > > >> >>>>>>>>> >>>>>>> or `eval` >> > > >> >>>>>>>>> >>>>>>> etc). The compiler figure out the >> > > creation/lifetime of >> > > >> >>>>>>>>> >>>>>>> all >> > > >> >>>>>>>>> >>>>>>> local >> > > >> >>>>>>>>> >>>>>>> variables (at compile time). Therefore, to >> > > access a >> > > >> >>>>>>>>> >>>>>>> variable in the >> > > >> >>>>>>>>> >>>>>>> parent scope: >> > > >> >>>>>>>>> >>>>>>> >> > > >> >>>>>>>>> >>>>>>> 1. If it's a global, then it need a runtime >> > > >> >>>>>>>>> >>>>>>> lookup/binding >> > > >> >>>>>>>>> >>>>>>> (the >> > > >> >>>>>>>>> >>>>>>> reason >> > > >> >>>>>>>>> >>>>>>> global are slow) >> > > >> >>>>>>>>> >>>>>>> 2. If it's in a parent non-global scope, the >> > > compiler >> > > >> >>>>>>>>> >>>>>>> can >> > > >> >>>>>>>>> >>>>>>> figure out >> > > >> >>>>>>>>> >>>>>>> how to bind/access it at compile time and no >> > > extra >> > > >> >>>>>>>>> >>>>>>> (lookup) >> > > >> >>>>>>>>> >>>>>>> code at >> > > >> >>>>>>>>> >>>>>>> runtime is necessary. >> > > >> >>>>>>>>> >>>>>>> >> > > >> >>>>>>>>> >>>>>>> >> >> > > >> >>>>>>>>> >>>>>>> > >> > > >> >>>>>>>>> >>>>>>> > A julia local variable is basically a >> > > variable in C. >> > > >> >>>>>>>>> >>>>>>> > There's a >> > > >> >>>>>>>>> >>>>>>> > table >> > > >> >>>>>>>>> >>>>>>> > at compile time to map between symbols and >> > > stack slots >> > > >> >>>>>>>>> >>>>>>> > (or >> > > >> >>>>>>>>> >>>>>>> > whereever >> > > >> >>>>>>>>> >>>>>>> > they are stored) but such a map does not >> > > exist at >> > > >> >>>>>>>>> >>>>>>> > runtime >> > > >> >>>>>>>>> >>>>>>> > anymore >> > > >> >>>>>>>>> >>>>>>> > (except for debugging). >> > > >> >>>>>>>>> >>>>>>> > >> > > >> >>>>>>>>> >>>>>>> >> >> > > >> >>>>>>>>> >>>>>>> >> On Wednesday, July 8, 2015 at 7:34:09 PM >> > > UTC-4, >> > > >> >>>>>>>>> >>>>>>> >> Brandon >> > > >> >>>>>>>>> >>>>>>> >> Taylor >> > > >> >>>>>>>>> >>>>>>> >> wrote: >> > > >> >>>>>>>>> >>>>>>> >>> >> > > >> >>>>>>>>> >>>>>>> >>> They must exist at runtime and at local >> > > scope. >> > > >> >>>>>>>>> >>>>>>> >>> Evaluating a >> > > >> >>>>>>>>> >>>>>>> >>> symbol is >> > > >> >>>>>>>>> >>>>>>> >>> impossible without a pool of defined >> > > symbols in >> > > >> >>>>>>>>> >>>>>>> >>> various >> > > >> >>>>>>>>> >>>>>>> >>> scopes to >> > > >> >>>>>>>>> >>>>>>> >>> match it >> > > >> >>>>>>>>> >>>>>>> >>> to. Unless I'm missing something? >> > > >> >>>>>>>>> >>>>>>> >>> >> > > >> >>>>>>>>> >>>>>>> >>> On Wednesday, July 8, 2015 at 7:26:27 PM >> > > UTC-4, >> > > >> >>>>>>>>> >>>>>>> >>> Jameson >> > > >> >>>>>>>>> >>>>>>> >>> wrote: >> > > >> >>>>>>>>> >>>>>>> >>>> >> > > >> >>>>>>>>> >>>>>>> >>>> There are global symbol tables for static >> > > analysis >> > > >> >>>>>>>>> >>>>>>> >>>> / >> > > >> >>>>>>>>> >>>>>>> >>>> reflection, >> > > >> >>>>>>>>> >>>>>>> >>>> but they >> > > >> >>>>>>>>> >>>>>>> >>>> do not exist at runtime or for the local >> > > scope. >> > > >> >>>>>>>>> >>>>>>> >>>> >> > > >> >>>>>>>>> >>>>>>> >>>> On Wed, Jul 8, 2015 at 7:06 PM Brandon >> > > Taylor >> > > >> >>>>>>>>> >>>>>>> >>>> <brandon....@gmail.com> >> > > >> >>>>>>>>> >>>>>>> >>>> wrote: >> > > >> >>>>>>>>> >>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>> Surely environments already exist >> > > somewhere inside >> > > >> >>>>>>>>> >>>>>>> >>>>> Julia? How >> > > >> >>>>>>>>> >>>>>>> >>>>> else could >> > > >> >>>>>>>>> >>>>>>> >>>>> you keep track of scope? It would be >> > > simply a >> > > >> >>>>>>>>> >>>>>>> >>>>> matter >> > > >> >>>>>>>>> >>>>>>> >>>>> of >> > > >> >>>>>>>>> >>>>>>> >>>>> granting users >> > > >> >>>>>>>>> >>>>>>> >>>>> access to them. Symbol tables in a >> > > mutable >> > > >> >>>>>>>>> >>>>>>> >>>>> language >> > > >> >>>>>>>>> >>>>>>> >>>>> are by >> > > >> >>>>>>>>> >>>>>>> >>>>> default mutable. >> > > >> >>>>>>>>> >>>>>>> >>>>> It would certainly be possible only give >> > > users >> > > >> >>>>>>>>> >>>>>>> >>>>> access >> > > >> >>>>>>>>> >>>>>>> >>>>> to >> > > >> >>>>>>>>> >>>>>>> >>>>> immutable >> > > >> >>>>>>>>> >>>>>>> >>>>> reifications (which could solve a bunch >> > > of >> > > >> >>>>>>>>> >>>>>>> >>>>> problems >> > > >> >>>>>>>>> >>>>>>> >>>>> as is). >> > > >> >>>>>>>>> >>>>>>> >>>>> However, it >> > > >> >>>>>>>>> >>>>>>> >>>>> seems natural to match mutable symbol >> > > tables with >> > > >> >>>>>>>>> >>>>>>> >>>>> mutable >> > > >> >>>>>>>>> >>>>>>> >>>>> reifications, and >> > > >> >>>>>>>>> >>>>>>> >>>>> immutable symbol tables with immutable >> > > >> >>>>>>>>> >>>>>>> >>>>> reifications. >> > > >> >>>>>>>>> >>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>> On Wednesday, July 8, 2015 at 6:50:03 PM >> > > UTC-4, >> > > >> >>>>>>>>> >>>>>>> >>>>> Brandon Taylor >> > > >> >>>>>>>>> >>>>>>> >>>>> wrote: >> > > >> >>>>>>>>> >>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>> I'm not sure I understand... >> > > >> >>>>>>>>> >>>>>>> >>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>> On Wednesday, July 8, 2015 at 6:24:37 >> > > PM UTC-4, >> > > >> >>>>>>>>> >>>>>>> >>>>>> John >> > > >> >>>>>>>>> >>>>>>> >>>>>> Myles >> > > >> >>>>>>>>> >>>>>>> >>>>>> White wrote: >> > > >> >>>>>>>>> >>>>>>> >>>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>>> Reified scope makes static analysis >> > > much too >> > > >> >>>>>>>>> >>>>>>> >>>>>>> hard. >> > > >> >>>>>>>>> >>>>>>> >>>>>>> Take any >> > > >> >>>>>>>>> >>>>>>> >>>>>>> criticism >> > > >> >>>>>>>>> >>>>>>> >>>>>>> of mutable state: they all apply to >> > > globally >> > > >> >>>>>>>>> >>>>>>> >>>>>>> mutable symbol >> > > >> >>>>>>>>> >>>>>>> >>>>>>> tables. >> > > >> >>>>>>>>> >>>>>>> >>>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>>> On Wednesday, July 8, 2015 at 10:26:23 >> > > PM UTC+2, >> > > >> >>>>>>>>> >>>>>>> >>>>>>> Milan >> > > >> >>>>>>>>> >>>>>>> >>>>>>> Bouchet-Valat >> > > >> >>>>>>>>> >>>>>>> >>>>>>> wrote: >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> Le mercredi 08 juillet 2015 à 13:20 >> > > -0700, >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> Brandon >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> Taylor a >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> écrit : >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> > All functions. >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> Well, I don't know of any language >> > > which >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> doesn't >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> have >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> scoping >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> rules... >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> Anyway, I didn't say scoping rules >> > > are >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> necessarily >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> confusing, I was >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> only referring to R formulas. But >> > > according to >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> the >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> examples >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> you >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> posted, >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> your question appears to be >> > > different. >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> >> > > >> >>>>>>>>> >>>>>>> >>>>>>>> >> >