-
Notifications
You must be signed in to change notification settings - Fork 371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Eval should use globals + locals #1043
Conversation
Travis is complaining. Also globals+locals isn't the current environment, since nonlocals don't work e.g. (((fn []
(setv spam 42)
(fn [] (eval 'spam)))))
;; NameError But something similar in Clojure would work: user=> (((fn [] (let [spam 42] (fn [] (eval 'spam))))))
42 It also works in Hy without the eval: => (((fn []
... (setv spam 42)
... (fn [] spam))))
def _hy_anon_fn_2():
spam = 42
def _hy_anon_fn_1():
return spam
return _hy_anon_fn_1
_hy_anon_fn_2()()
42 |
Another potential issue: Overall, Hy's eval seems to work more like Python's than like Lisp's. I wonder if this is the wrong approach. How does our REPL even function without a proper eval? Can we just use that for eval instead? |
A typical Lisp eval, as in Common Lisp, accepts a form as the parameter and computes its value using the dynamic environment to provide meaning for names in the form. The user eval is really a front-end for the internal one which takes an environment as a parameter as macro-expand-1 does. Maybe there’s a way to map the Python concept of module-level scope to a dynamic environment in Lisp?
|
@gilch Well that sucks... There's only one true solution I can think of: do it like shown in this PR, but also merge it with the result of a new function, def get_freevars(func):
closure = func.__closure__
freevars = func.__code__.co_freevars
return dict(zip(freevars, (cell.cell_contents for cell in closure))) Now, def _hy_anon_fn_1(): # Or whatever...
_hy_current_function = _hy_anon_fn_1 then |
There's still the problem of assignment. What happens if you I'm not sure how well the def _hy_anon_fn_1():
_hy_current_function = _hy_anon_fn_1
foo = 42
def _hy_anon_fn_2():
_hy_current_function = _hy_anon_fn_1 # used in _hy_anon_fn_3, so compiler put it in.
new_hy_eval(HySymbol('foo'),_hy_current_function) # oops
def _hy_anon_fn_3(): ... |
@gilch At this point, I would just deem assignment broken, especially since it's virtually impossible under Python 3 (in Python 2, you could just put Back to the topic... ... ...actually, can't we just define |
That does sound like a better plan, if it works. However, that would mean you can't pass |
@gilch You can't even do that right now; Hy will pass Python's |
Can't figure this out, and sadly don't have the time. :( |
Fixes #1041. @gilch Can you confirm this fixes it for you?