[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Scope in Method Definitions

Curt Sampson

4/13/2005 6:22:00 AM

4 Answers

Gennady

4/13/2005 6:42:00 AM

0


On Apr 12, 2005, at 11:21 PM, Curt Sampson wrote:

>
> Presumably there's some theory behind this, but this is a seeming
> inconsistency in the language that I don't understand.
>
> foo = "foo"
> C = Class.new() {
> def method1; puts foo; end

Here method1's local variable (as there's no foo() method so far) is
being referenced and it is not defined.

> define_method(:method2) { puts foo }

Here a block is used that defines the closure referencing the local
variable foo from the current scope.
Looks pretty consistent ;-)

> }

Oh, yes, a block is used to define a class body, I see. However, "def"
syntax prevents "foo" from being treated as a closure participant. At
least, it is how it looks to me ;-).

>
> C.new.method2 # prints "foo"
> C.new.method1 # NameError: undefined local variable or method `foo'
>
> Can someone explain why this is sensible behaviour?
>
> cjs
> --
> Curt Sampson <cjs@cynic.net> +81 90 7737 2974
> http://www....
> Make up enjoying your city life...produced by BIC CAMERA
>
>

Gennady.



Curt Sampson

4/13/2005 6:53:00 AM

0

Pit Capitain

4/13/2005 6:55:00 AM

0

Curt Sampson schrieb:
>
> Presumably there's some theory behind this, but this is a seeming
> inconsistency in the language that I don't understand.
>
> foo = "foo"
> C = Class.new() {
> def method1; puts foo; end
> define_method(:method2) { puts foo }
> }
>
> C.new.method2 # prints "foo"
> C.new.method1 # NameError: undefined local variable or method `foo'
>
> Can someone explain why this is sensible behaviour?

Your code can be reduced to

foo = "foo"
def m1; p foo; end
m2 = lambda { p foo }

m2.call # => "foo"
m1.call # => NameError

Does this help?

Regards,
Pit


Robert Klemme

4/13/2005 8:35:00 AM

0


"Curt Sampson" <cjs@cynic.net> schrieb im Newsbeitrag
news:Pine.NEB.4.62.0504131544280.19224@angelic.cynic.net...
> On Wed, 13 Apr 2005, Gennady Bystritsky wrote:
>
> > Oh, yes, a block is used to define a class body, I see. However, "def"
> > syntax prevents "foo" from being treated as a closure participant. At
> > least, it is how it looks to me ;-).
>
> Bingo! After a bit more playing, it looks like the "class" statement
> does this too.
>
> This is not so hard to live with, once you know. The problem is, the
> language makes finding out this stuff so darn tough.
>
> If you want to see what this was all about, I've appended a nifty little
> bit of code. (I'm using it with a factory that stores Classes, and
> later instantiates them; this saves me having to store parameters for
> new as well.) It took me quite some time to work out that I had to use
> define_method instead of def.
>
> cjs
> --
> Curt Sampson <cjs@cynic.net> +81 90 7737 2974 http://www....
> Make up enjoying your city life...produced by BIC CAMERA
>
>
> # $Id: curry.rb,v 1.1 2005/04/13 05:41:38 cjs Exp $
>
> require 'test/unit/testcase'
>
> def curryclass(klass, *curried_args)
> curried_class = Class.new(klass) {
> def initialize(*args)
> super_args = curried_args + args
> super(*super_args)
> end
> }
> curried_class
> end

I'd probably do it either of these ways:

# straightforward, but need to invoke #call
def curryclass(cl,*args)
lambda { cl.new(*args) }
end

# if you need "new"
def curryclass(cl,*args)
l = lambda { cl.new(*args) }
class <<l; alias :new :call; end
l
end

# another way
def curryclass(cl,*args)
o = Object.new
class <<o;self;end.define_method(:new){cl.new(*args)}
o
end

Kind regards

robert


> class TC_curryclass < Test::Unit::TestCase
>
> class AddPair
> def initialize(a, b)
> @value = a + b
> end
> attr_reader :value
> end
>
> AddTwoAndFour = curryclass(AddPair, 2, 4)
>
> AddTwo = curryclass(AddPair, 2)
>
> def FAILING test_curryclass
> assert_equal(5, self.class::AddPair.new(2, 3).value)
> assert_equal(6, self.class::AddTwoAndFour.new.value)
> assert_equal(7, self.class::AddTwo.new(5).value)
> end
>
> def test_nothing
> end
>
> end
>
>