using ala pascal

S

Simon Strandgaard

I have some class hierarchies located in different modules, but with
clashing names, thus I cannot 'include' the modules.
Basicly what im interested in is something similar to 'using' in pascal.
Any advice would be appreciated :)

Q1: using ?

Q2: Is it possible to make an alias for a module, so that I for instance
only have to type X::Test when I refer to LongModuleName1::Test ?

--
Simon Strandgaard


module LongModuleName1
class Test
def to_s; "1" end
end
end

class Test
def initialize
using(LongModuleName1) { # would be nice
@value = Test.new
}
end
def to_s
@value.to_s
end
end

p Test.new.to_s # => "2"
 
J

Jason Williams

Q2: Is it possible to make an alias for a module, so that I for instance
only have to type X::Test when I refer to LongModuleName1::Test ?

This bit's easy enough - "X = LongModuleName1" should work fine, I
think.
 
S

Simon Strandgaard

This bit's easy enough - "X = LongModuleName1" should work fine, I
think.

Sorry.. that doesn't work


server> ruby a.rb
a.rb:9: dynamic constant assignment
X = LongModuleName1
^
server> expand -t2 a.rb
module LongModuleName1
class Test
def to_s; "1" end
end
end

class Test
def initialize
X = LongModuleName1
@value = X::Test.new
end
def to_s
@value.to_s
end
end

p Test.new.to_s # => "1"
server>
 
J

Jason Williams

Simon Strandgaard said:
Sorry.. that doesn't work

Oh, peculiar. I tried this code, and it worked okay -

module LongModuleName
class Wibble ; end
end

X = LongModuleName

puts X::Wibble
 
S

Simon Strandgaard

This bit's easy enough - "X = LongModuleName1" should work fine, I
think.

However using a lowercase letter, then it works :)


server> ruby a.rb
"1"
server> expand -t2 a.rb
module LongModuleName1
class Test
def to_s; "1" end
end
end

class Test
def initialize
x = LongModuleName1
@value = x::Test.new
end
def to_s
@value.to_s
end
end

p Test.new.to_s # => "1"
server>
 
G

gabriele renzi

il Sun, 26 Oct 2003 13:39:26 +0100, Simon Strandgaard
On Sun, 26 Oct 2003 12:20:10 +0000, Jason Williams wrote:


Sorry.. that doesn't work


server> ruby a.rb
a.rb:9: dynamic constant assignment
X = LongModuleName1
^
server> expand -t2 a.rb
module LongModuleName1
class Test
def to_s; "1" end
end
end

class Test
def initialize
X = LongModuleName1
@value = X::Test.new
end
def to_s
@value.to_s
end
end

this fails cause you are doing it in a method.
You can do it safely with const_set

irb(main):001:0> def f
irb(main):002:1> Object::const_set 'X',Math::pI
irb(main):003:1> end
=> nil
irb(main):004:0> f
=> 3.14159265358979
irb(main):005:0> X
=> 3.14159265358979
 
S

Simon Strandgaard

I have some class hierarchies located in different modules, but with
clashing names, thus I cannot 'include' the modules.
Basicly what im interested in is something similar to 'using' in pascal.
Any advice would be appreciated :)

Q1: using ?


Damn.. Actually I am thinking of the 'with' keyword in pascal.
Question: Any ideas on how to accomplish something similar in Ruby ?
 
G

gabriele renzi

il Sun, 26 Oct 2003 16:49:24 +0100, Simon Strandgaard
Damn.. Actually I am thinking of the 'with' keyword in pascal.
Question: Any ideas on how to accomplish something similar in Ruby ?

Oh I was wondering what the hell that keyword meant :)

the trick is easy:

def with(object, &block)
object.instance_eval(&block)
end

with 'ciao' do
p length
p id
end
 
S

Simon Strandgaard

il Sun, 26 Oct 2003 16:49:24 +0100, Simon Strandgaard


Oh I was wondering what the hell that keyword meant :)

the trick is easy:

def with(object, &block)
object.instance_eval(&block)
end

with 'ciao' do
p length
p id
end

What am I doing wrong here ?

--
Simon Strandgaard

server> ruby a.rb
a.rb:11:in `test': uninitialized constant A (NameError)
from a.rb:10:in `instance_eval'
from a.rb:2:in `instance_eval'
from a.rb:2:in `with'
from a.rb:10:in `test'
from a.rb:16
server> expand -t2 a.rb
def with(object, &block)
object.instance_eval(&block)
end
module ModuleTest
class A
def test; 42 end
end
end
def test
with(ModuleTest) {
with(A.new) {
p test
}
}
end
test
server>
 
R

Robert Klemme

gabriele renzi said:
il Sun, 26 Oct 2003 13:39:26 +0100, Simon Strandgaard


this fails cause you are doing it in a method.
You can do it safely with const_set

irb(main):001:0> def f
irb(main):002:1> Object::const_set 'X',Math::pI
irb(main):003:1> end
=> nil
irb(main):004:0> f
=> 3.14159265358979
irb(main):005:0> X
=> 3.14159265358979

Much simpler - just directly assign it in class scope:

module LongModuleName1
class Test
def to_s; "1" end
end
end

class Test
X = LongModuleName1

def initialize
@value = X::Test.new
end
def to_s
@value.to_s
end
end

p Test.new.to_s # => "1"

robert
 
R

Robert Klemme

Simon Strandgaard said:
However using a lowercase letter, then it works :)

Well, then x is a locl variable. But if you generally want to refer to
LongModuleName1 as X inside class Test then a constant is much better,
because it's more efficient (only one assignment):
server> ruby a.rb
"1"
server> expand -t2 a.rb
module LongModuleName1
class Test
def to_s; "1" end
end
end

class Test

X = LongModuleName1
def initialize
@value = x::Test.new
end
def to_s
@value.to_s
end
end

p Test.new.to_s # => "1"
server>

Cheers

robert
 
R

Robert Klemme

Simon Strandgaard said:
What am I doing wrong here ?

--
Simon Strandgaard

server> ruby a.rb
a.rb:11:in `test': uninitialized constant A (NameError)
from a.rb:10:in `instance_eval'
from a.rb:2:in `instance_eval'
from a.rb:2:in `with'
from a.rb:10:in `test'
from a.rb:16
server> expand -t2 a.rb
def with(object, &block)
object.instance_eval(&block)
end
module ModuleTest
class A
def test; 42 end
end
end
def test
with(ModuleTest) {
with(A.new) {
p test
}
}
end
test
server>

It doesn't work with constants. In order to make this work you'd have to
do:

def test
with(ModuleTest) {
with(const_get('A').new) {
p test
}
}
end

which isn't really nice. This one's better:

def test
with(ModuleTest::A.new) {
p test
}
end

Apart from that I'd define with in Kernel like:

def Kernel.with(object, &block)
object.instance_eval(&block)
end

That way, you can use it everywhere.


Another option is:

class Object
alias with instance_eval
end

Now you can do

def test
ModuleTest::A.new.with {
p test
}
end

Kind regards

robert
 
S

Simon Strandgaard

[snip]

It doesn't work with constants. In order to make this work you'd have to
do:

def test
with(ModuleTest) {
with(const_get('A').new) {
p test
}
}
end

which isn't really nice. This one's better:

def test
with(ModuleTest::A.new) {
p test
}
end

I often has a serious need for the first form.. with(ModuleTest).
The second 'better' form, is not what I am looking fore.
How to implement the first form ?


I am no expert in 'eval' and 'binding'.. It would be nice if the parent
scope were inherited.. So that the following piece of code would work.
Any ideas how to make it behave like pascals 'with' keyword?



server> ruby b.rb
b.rb:17:in `with': wrong number of arguments (1 for 0) (ArgumentError)
from b.rb:17:in `test'
from b.rb:26
server> expand -t2 b.rb
class Object
alias with instance_eval
end
module Kernel
def with(object, &block)
object.instance_eval(&block)
end
end
module LongModuleName1
def test; 13 end
end
module LongModuleName2
def test; 29 end
end
class Test
def test
with(LongModuleName1) {
a = test
}
LongModuleName2.with {
b = test
}
a + b # 13 + 29
end
end
p Test.new.test #=> 42
server>
 
R

Robert Klemme

Simon Strandgaard said:
Damn.. Actually I am thinking of the 'with' keyword in pascal.
Question: Any ideas on how to accomplish something similar in Ruby ?
[snip]

It doesn't work with constants. In order to make this work you'd have to
do:

def test
with(ModuleTest) {
with(const_get('A').new) {
p test
}
}
end

which isn't really nice. This one's better:

def test
with(ModuleTest::A.new) {
p test
}
end

I often has a serious need for the first form.. with(ModuleTest).
The second 'better' form, is not what I am looking fore.
How to implement the first form ?


I am no expert in 'eval' and 'binding'.. It would be nice if the parent
scope were inherited.. So that the following piece of code would work.
Any ideas how to make it behave like pascals 'with' keyword?

You can come closer with this definition of "with":

module Kernel
def with(obj, &b)
if obj.kind_of? Symbol
obj = ( self.kind_of?( Module ) ? self : self.class ).const_get(
obj )
end

obj.instance_eval(&b)
end
end

module Foo
class Bar
end
end

with( :Foo ) do
with( :Bar ) do
p self.new
end
end

with( Foo ) do
with( :Bar ) do
p self.new
end
end


You can't do this:

with( Foo ) do
with( Bar ) do
p self.new
end
end

Because "Bar" is looked up in global scope.

Regards

robert
 
S

Simon Strandgaard

Simon Strandgaard said:
Damn.. Actually I am thinking of the 'with' keyword in pascal.
Question: Any ideas on how to accomplish something similar in Ruby ? [snip]
I am no expert in 'eval' and 'binding'.. It would be nice if the parent
scope were inherited.. So that the following piece of code would work.
Any ideas how to make it behave like pascals 'with' keyword?
[snip]

You can't do this:

with( Foo ) do
with( Bar ) do
p self.new
end
end

Because "Bar" is looked up in global scope.

Ok.. thats a shame.. some day I better play around with and explore
Rubys eval + binding capabilities. So that I can understand whats going
on.

Thanks for your insight Robert.


Can anyone point to an online resource about eval+binding ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,351
Latest member
LolaD32479

Latest Threads

Top