Hello all.
During last several monthes I’ve worked on some library, using the
latest
ruby1.9. Now I want to release the library to community, but first I
need to
“backport” it.
One small problem I’ve stumbled upon:
module Constants
TEST = 5
end
class A
end
a = A.new
a.instance_eval{
extend Constants
p TEST #<== here
}
At the “here” string, ruby1.9 had printed “5”, but ruby 1.8.5 raises
NameError (uninitialized constant TEST).
I know, the question is silly, but I can’t find how to do this. (by some
reasons, the code should affect only one object, not entire class)
Thanks.
V.
On Feb 11, 2007, at 7:02 PM, Victor Zverok S. wrote:
extend Constants
p TEST #<== here
}
The only solutions I can think of involve explicitly referencing the
class:
class Object
def singleton_class
(class <<self; self; end)
end
end
a.instance_eval {
extend Constants
singleton_class::TEST
}
But at that point it is probably easier to simply reference Constants
directly:
a.instance_eval {
t = Constants::TEST
}
It does seem a bit strange to be adding constants to the singleton
class.
Why not add them to A itself? That way you don’t need to extend the
singleton class with the Constants module.
class A
include Constants
end
A.new.instance_eval {
p self.class::TEST # still a bit ugly…
}
Gary W.
On Mon, 12 Feb 2007 09:02:37 +0900, Victor “Zverok” Shepelev wrote:
At the “here” string, ruby1.9 had printed “5”, but ruby 1.8.5 raises
NameError (uninitialized constant TEST).
I know, the question is silly, but I can’t find how to do this. (by some
reasons, the code should affect only one object, not entire class)
class << a
extend Constants
p TEST
end
From: Gary W. [mailto:[email protected]]
Sent: Monday, February 12, 2007 2:33 AM
a.instance_eval{
extend Constants
p TEST #<== here
}
[…]
A.new.instance_eval {
p self.class::TEST # still a bit ugly…
}
Just due to this ugliness, and, additionally, I can’t (or don’t want)
modify
entire “A” class. More specifically, I have something like “scripts” -
files, which are loaded and evaluated inside some objects. For example
(it’s
about new GUI library, BTW):
File tabs.rs (“rs” for “Ruby Script”
extend Win32::Keys
on(TAB) do
…blah
end
on(SHIFT, TAB) do
… blah, blah
end
This “script” is represents “tabs” behavior and it is evaluated in
context
of UI element, which I want this behavior to be added.
The more verbose version, which is enforced by ruby 1.8.5, I don’t like
at
all:
on(Win32::Keys::TAB) do #fuuuuuu!
It’s a problem, so
V.
On Feb 11, 2007, at 7:41 PM, Victor Zverok S. wrote:
Just due to this ugliness, and, additionally, I can’t (or don’t
want) modify
entire “A” class. More specifically, I have something like “scripts” -
files, which are loaded and evaluated inside some objects. For
example (it’s
about new GUI library, BTW):
This uses eval on a string, which can be dangerous, but if you are
already
reading script files and executing them…
module X
TEST = 5
end
class A; end
a = A.new
class <<a
def instance_binding
binding
end
end
script = “extend X; p TEST” # could read this from a file
eval script, a.instance_binding # XXX dangerous
From: Gary W. [mailto:[email protected]]
Sent: Monday, February 12, 2007 3:26 AM
reading script files and executing them…
binding
end
end
script = “extend X; p TEST” # could read this from a file
eval script, a.instance_binding # XXX dangerous
Thanks, Gary.
I suppose, it’s the only way to have constants from some module visible
inside some_object.instance_eval ?
V.
From: Ken B. [mailto:[email protected]]
Sent: Monday, February 12, 2007 3:10 AM
module Constants
p TEST #<== here
p TEST
end
Not exactly what I want.
I need “TEST” constant to be visible inside a.instance_eval
V.
On Feb 11, 2007, at 8:28 PM, Victor “Zverok” Shepelev wrote:
Thanks, Gary.
I suppose, it’s the only way to have constants from some module
visible
inside some_object.instance_eval ?
Maybe someone else will come up with something but I think the main
problem is that instance_eval with a code block does not actually
provide the same binding context as a method definition within a class
block. That is what led me to grabbing the exact context you were
looking for with Kernel#binding and using the string version of eval.
I haven’t reviewed the Ruby 1.9 constant lookup changes recently but
I think that they lean towards a more ‘dynamic’ rather than
‘lexical’ approach, which seems to be what a lot of people expect and
get surprised by in Ruby 1.8.X.
Gary W.
On Mon, 12 Feb 2007 09:41:24 +0900, Victor “Zverok” Shepelev wrote:
class.
…blah
all:
on(Win32::Keys::TAB) do #fuuuuuu!
It’s a problem, so
V.
How about
C=Win32::Keys
on(C::TAB) do
…blah
end
on(C::SHIFT, C::TAB) do
… blah, blah
end
(or even use c instead of C so you don’t allocate another constant)
Victor “Zverok” Shepelev wrote:
At the “here” string, ruby1.9 had printed “5”, but ruby 1.8.5 raises
NameError (uninitialized constant TEST).
module Constants
TEST = 5
end
class A
end
a = A.new
m = Module.new
def m.const_missing k
Constants.const_get(k) || super(k)
end
string_from_file = <<END
TEST
END
test = m.module_eval %{
a.instance_eval {
#{string_from_file}
}
}
p test # ==> 5