Forum: Ruby Backport from ruby 1.9, including constants

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Victor "Zverok" Shepelev (Guest)
on 2007-02-12 02:03
(Received via mailing list)
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.
Gary W. (Guest)
on 2007-02-12 02:33
(Received via mailing list)
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.
Victor "Zverok" Shepelev (Guest)
on 2007-02-12 02:42
(Received via mailing list)
From: Gary W. [mailto:removed_email_address@domain.invalid]
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.
Ken B. (Guest)
on 2007-02-12 03:11
(Received via mailing list)
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
Victor "Zverok" Shepelev (Guest)
on 2007-02-12 03:18
(Received via mailing list)
From: Ken B. [mailto:removed_email_address@domain.invalid]
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.
Gary W. (Guest)
on 2007-02-12 03:26
(Received via mailing list)
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
Victor "Zverok" Shepelev (Guest)
on 2007-02-12 03:29
(Received via mailing list)
From: Gary W. [mailto:removed_email_address@domain.invalid]
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.
Gary W. (Guest)
on 2007-02-12 04:09
(Received via mailing list)
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.
Ken B. (Guest)
on 2007-02-12 04:11
(Received via mailing list)
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)
Joel VanderWerf (Guest)
on 2007-02-12 06:00
(Received via mailing list)
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
This topic is locked and can not be replied to.