-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Interactive scopes #51434
Comments
The scoped value being constant within a particular scope is an important semantic piece. I would loathe to give that up. The REPL could manage the scope, but Intentionally didn't expose a So REPL could have a |
I agree, though the pattern I outlined above is effectively doing that via other means. I don't think it is something we should encourage.
You mean a function which changes the scope of the current task? That's sort of what I want: can you expand on what your concerns are? Is it that you want the compiler to be able to assume that scoped values are unchanged outside of What if we had something weaker, e.g. changes to the scope would only be reflected at top-level (similar to how eval works)?
How would this be easier to reason about? |
Yeah pretty much. I want to leave the door open for #51352
Maybe? That's what I was thinking with
Yeah, it's not something we can stop people from doing :) You could also put a Ref in there and mutate it directly. |
I could see there also being some advantage to allowing something similar in scripts as well, e.g. setting the logger at the start of a program. |
I do see the appeal, but I am unsure about the semantics and the implications. The overall problem is when to restore the previous scope, what is scope exit. I honestly don't mind making precision a Ref, and then set precision modifying the ref within the current scope. You still limit the effect of that operation and that's a boon |
How about this: make macro setscope!(exprs...)
Expr(:toplevel, quote
ct = Base.current_task()
ct.scope = Base.ScopedValues.Scope(ct.scope, $(map(esc, exprs)...))
end)
end then this would prevent it being called inside a function julia> function setprec(n)
@setscope!(Base.MPFR.CURRENT_PRECISION => n)
end
ERROR: syntax: "toplevel" expression not at top level
Stacktrace:
[1] top-level scope
@ REPL[9]:1 We could either then implement julia> macro setscope!(exprs...)
Expr(:toplevel, quote
ct = Base.current_task()
ct.scope = Base.ScopedValues.Scope(ct.scope, $(map(esc, exprs)...))
end)
end
@setscope! (macro with 1 method)
julia> function setprec_eval(n)
@eval (@setscope!(Base.MPFR.CURRENT_PRECISION => $n))
end
setprec_eval (generic function with 1 method)
julia> precision(BigFloat)
256
julia> setprec_eval(128)
Base.ScopedValues.Scope(ScopedValue{Int64}@0x17c8c76e2041a828 => 128)
julia> precision(BigFloat)
128 though I'm not sure this would give the semantics you had in mind. |
I don't like the use eval there, but making it a macro also seems odd. I think my issue is that the lifetime/extent of the ScopedValue is ambiguous, but I guess |
I think a good way to implement this would be to have the REPL enter a normal |
Aside: one thing I hate about nested REPLs that you exit with ^D is that it makes it really easy to accidentally exit your whole REPL session. |
Looking at how
ScopedValue
s are used for the logger (#50958) and my proposed use for MPFR precision and rounding (#51362), we've ended up with a pattern where if theScopedValue
isn't defined, we fall back on a globalRef
value which can be set globally, defining an accessor like:If this is going to be common, it seems like a clunky pattern. One straightforward solution would be to make the
default
field mutable (which would remove the need for this pattern), but it is perhaps worth considering why this is used.@vchuravy asked if it was important if we be able to set the precision globally. I mentioned backward compatibility, but the primary rationale is for interactivity: if I want to increase the precision for all my last calculation, I can just call
setprecision(BigFloat, 1024)
, and then re-evaluate the expression (hit up arrow twice, and return). If I didn't have this ability, I would have to wrap everything expression insetprecision(BigFloat, 1024) do .... end
, which is fiddly and time consuming.However, if we had some way to evaluate inside a given scope at the REPL, this might not be necessary: basically what I want is something similar to the contextual module REPL, but for scopes.
The text was updated successfully, but these errors were encountered: