Hi guys, I am a recent Ruby convert (from PERL), and I am wondering if there
is a way to get some of the behavior that I am
comfortable with with regards to scope.
In PERL the following code:
my $var=1;
{
my $var=2;
print "inner=$var\n"
}
print "outer=$var\n"
yields:
inner=2
outer=1
However in Ruby, I'm not sure how to get the same behavior. I tried:
var=1
begin
var=2
print "inner=#{var}\n"
end
print "outer=#{var}\n"
which yields a different output than the PERL code. Is this type of thing
possible in Ruby without creating a class?
If the variables really are different, then use a different variable
name. Even though you can do this in perl, that does not make it a good
idea.
Methods should, in general, be short enough that you do not have naming
conflicts between local variables. If you find yourself running into
this a lot, you are probably doing too much in one method, which can
make code harder to read and to refactor later on.
Matz has discussed some syntaxes for what you want for Ruby 2.0, such
as:
var = 1
local { |var|
var = 2
}
puts var #=> 1
(so that block parameters are always local to the block) but I don't
know what the current status of this is.
Paul
···
On Tue, Sep 18, 2007 at 11:29:25PM +0900, Mister Rohit wrote:
my $var=1;
{
my $var=2;
print "inner=$var\n"
}
print "outer=$var\n"
irb(main):001:0> def m
irb(main):002:1> var = 2
irb(main):003:1> puts "inner var = #{var}"
irb(main):004:1> end
=> nil
irb(main):005:0> var = 1
=> 1
irb(main):006:0> m
inner var = 2
=> nil
irb(main):007:0> puts "outer var = #{var}"
outer var = 1
=> nil
you can nest methods too
irb(main):008:0> def m2
irb(main):009:1> var = 1
irb(main):010:1> def m3
irb(main):011:2> var = 2
irb(main):012:2> puts "inner var = #{var}"
irb(main):013:2> end
irb(main):014:1> puts "outer var = #{var}"
irb(main):015:1> end
=> nil
irb(main):016:0> m2
outer var = 1
=> nil
irb(main):017:0> m2.m3
outer var = 1
inner var = 2
=> nil
irb(main):018:0> m3
inner var = 2
=> nil
kind regards -botp
···
On 9/18/07, Mister Rohit <pigdog@gmail.com> wrote:
which yields a different output than the PERL code. Is this type of thing
possible in Ruby without creating a class?
irb(main):020:0> $VERBOSE = true
=> true
irb(main):023:0> m2.m3
(irb):9: warning: method redefined; discarding old m3
outer var = 1
inner var = 2
=> nil
irb(main):024:0> m2
(irb):9: warning: method redefined; discarding old m3
outer var = 1
=> nil
irb(main):025:0> nil.m3
inner var = 2
=> nil
(your example made it look like m3 is inside m2, which it isn't. m2 is
returning nil, and since you made m3 a public method, m2.m3 is the same as
m2(); nil.m3())
Paul
···
On Wed, Sep 19, 2007 at 12:59:58AM +0900, botp wrote:
irb(main):008:0> def m2
irb(main):009:1> var = 1
irb(main):010:1> def m3
irb(main):011:2> var = 2
irb(main):012:2> puts "inner var = #{var}"
irb(main):013:2> end
irb(main):014:1> puts "outer var = #{var}"
irb(main):015:1> end
=> nil
irb(main):016:0> m2
outer var = 1
=> nil
irb(main):017:0> m2.m3
outer var = 1
inner var = 2
=> nil
irb(main):018:0> m3
inner var = 2
=> nil
# On Wed, Sep 19, 2007 at 12:59:58AM +0900, botp wrote:
# > irb(main):008:0> def m2
# > irb(main):009:1> var = 1
# > irb(main):010:1> def m3
# > irb(main):011:2> var = 2
# > irb(main):012:2> puts "inner var = #{var}"
# > irb(main):013:2> end
# > irb(main):014:1> puts "outer var = #{var}"
# > irb(main):015:1> end
# > => nil
# > irb(main):016:0> m2
# > outer var = 1
# > => nil
# > irb(main):017:0> m2.m3
# > outer var = 1
# > inner var = 2
# > => nil
# > irb(main):018:0> m3
# > inner var = 2
# > => nil
···
From: Paul Brannan [mailto:pbrannan@atdesk.com]
#
# This might not be doing what you think it is:
#
# irb(main):020:0> $VERBOSE = true
# => true
# irb(main):023:0> m2.m3
# (irb):9: warning: method redefined; discarding old m3
# outer var = 1
# inner var = 2
# => nil
# irb(main):024:0> m2
# (irb):9: warning: method redefined; discarding old m3
# outer var = 1
# => nil
# irb(main):025:0> nil.m3
# inner var = 2
# => nil
my bad. sorry for the confusion.
i simply meant that you can define m3 inside m2, and that its var will not clash with that of m2, and that you can only invoke m3 if you've invoked m2 already.
in other words, you cannot do m3 right away. you'll have to do m2 first, or if you wish to run m3 immediately, you may follow it thru after m2, or m2.m3. i guess it would be clearer if i nest it further like m1.m2.m3.m4. i could go that route to reach m4 immediately, or just wait and just do m1; then later, m2, then later m3... from then on m4 will be defined and i could then just invoke it plainly as m4. (of course by this behaviour, one can also redefine methods by inserting them within methods)
pls correct me if i'm wrong, i usually make stupid assumptions based on my limited experience. pardon a nuby pls