I’m interested in figuring out a way to get a separate scope. I do not
need any other traditional sandbox features, i.e. any code goes, I
just want code evaluated in the scope to no affect the parent scope
(at all). Example illustrating what I am after:
a = 10
SeparatedScope.new do
a = a + 1
p a
end
p a
yielding:
11
10
I’d like it to have the same initialization/separation also for
instance variables and even global variables if possible.
Is something like that already available? If not, any good ideas for
how to implement it?
I did have a quick look at sandbox by _why, seems may do what I want
but not so keen on the interpreter patching etc so looking for
opportunities.
This is considerably more complicated (=uglier) than Bill’s
attempt. There’s even an eval lurking in there, which oughtn’t be
necessary when using macros. However, it does seem to fulfill all your
requirements.
A more sophisticated variable renaming scheme may be required if
you want your program to have variables which end with an underscore.
Use of eval inside a separated_scope will confuse things. Variables
used in the eval arg will refer to the outer scope, not the separated
scope.
Code that defines or uses macros must be pulled into the
interpreter using a special version of require: Macro.require. That’s
why there’s a separate file which requires ‘macro’, then calls
Macro.require.
Awesome! I had not seen rubymacros before. I’ll dig into this and try to
understand it in more detail.
a = 10
separated_scope do
a = a + 1
p a #=>11
end
p a #=>10
Commentary:
This is considerably more complicated (=uglier) than Bill’s
attempt. There’s even an eval lurking in there, which oughtn’t be
necessary when using macros. However, it does seem to fulfill all your
requirements.
A more sophisticated variable renaming scheme may be required if
you want your program to have variables which end with an underscore.
Use of eval inside a separated_scope will confuse things. Variables
used in the eval arg will refer to the outer scope, not the separated
scope.
Code that defines or uses macros must be pulled into the
interpreter using a special version of require: Macro.require. That’s
why there’s a separate file which requires ‘macro’, then calls
Macro.require.
If you get stuck or can’t understand something, don’t hesitate to ask
me.
Sweet I want to use macros. How about one to support ++
Hmm, I had thought that ruby’s immutable numeric types meant this was
impossible, but maybe it is feasible to implement as a macro… (not
as a method).
The big problem is that I haven’t (uh, yet) written the magic that
will allow users to define their own operators. (Or (re)define
existing operators as macros…)
But other than that, this ought to be possible… you’d need to use
different names until operator macros are defined, tho.
The preincrement version could be written like this:
macro preincr(n)
^n+=1 )
end
postincrement is somewhat more difficult. Here’s a first pass:
macro postincr(n)
(res=^n;^n+=1;res) )
end
(Warning: both increment macros are untested.)
but postincr is problematic. A call like:
postincr( a().b )
would cause a().b to be evaluated twice, which isn’t right. Solving
this, so that side effects in the arg to postincr are evaluated only
once, is more complicated, and I won’t attempt it here.
And nobody wants to type preincr or postincr (or even incr) when they
could just use +=1, so we’d really need user-defined operators
here…
?
Is that a self-portrait?
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.