[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

self in blocks

Vasco Andrade e silva

5/10/2007 9:37:00 PM

Hi

This seems to me somehow inconsistent:

class A; end

# 1)
# output A
A.class_eval { puts self }

# 2)
# output main (in irb)
[1].each { puts self }

The "problem" to me is that in 1) 'self' seems to refer to the context
where yield is called, where in 2) seems to refer to the context in
execution.
What should i expect from 'self'`s behaviour?

Tks
Vasco A. Silva

--
Posted via http://www.ruby-....

17 Answers

MenTaLguY

5/10/2007 9:42:00 PM

0

On Fri, 11 May 2007 06:37:07 +0900, Vasco Andrade e silva <vascoas@gmail.com> wrote:
> The "problem" to me is that in 1) 'self' seems to refer to the context
> where yield is called, where in 2) seems to refer to the context in
> execution.
> What should i expect from 'self'`s behaviour?

self will normally refer to self in the lexical scope of the block (#2). class_eval, module_eval, instance_eval, and instance_exec are special exceptions to this rule.

-mental


dblack

5/10/2007 9:46:00 PM

0

Gary Wright

5/10/2007 9:49:00 PM

0


On May 10, 2007, at 5:37 PM, Vasco Andrade e silva wrote:
> # 1)
> # output A
> A.class_eval { puts self }

One of the purposes of of #class_eval is to explicitly change
the binding of self within the block. By calling #class_eval
you are asking that self be bound to A (for your example) while
the block is executing. This is a behavior of class_eval and
not of blocks in general, which is why in:

[1].each { puts self }

self isn't bound to the array.

Gary Wright




Vasco Andrade e silva

5/10/2007 10:06:00 PM

0

MenTaLguY wrote:
> self will normally refer to self in the lexical scope of the block (#2).
> class_eval, module_eval, instance_eval, and instance_exec are special
> exceptions to this rule.
>
> -mental

I confess I don't like this approach :S (rules with exceptions, doesn't
fit right..) however thanks for the explanations.
By the way are class_eval, module_eval, instance_eval and instance_exec
the only exceptions?

Vasco A. Silva

--
Posted via http://www.ruby-....

dblack

5/10/2007 10:12:00 PM

0

MenTaLguY

5/10/2007 10:21:00 PM

0

On Fri, 11 May 2007 07:06:29 +0900, Vasco Andrade e silva <vascoas@gmail.com> wrote:

> By the way are class_eval, module_eval, instance_eval and instance_exec
> the only exceptions?

In Ruby's core library, yes. It's possible to implement new methods with similar behavior (which is occasionally useful), but that isn't the norm.

-mental


Gavin Kistner

5/10/2007 10:51:00 PM

0

On May 10, 4:21 pm, MenTaLguY <men...@rydia.net> wrote:
> On Fri, 11 May 2007 07:06:29 +0900, Vasco Andrade e silva <vasc...@gmail.com> wrote:
>
> > By the way are class_eval, module_eval, instance_eval and instance_exec
> > the only exceptions?
>
> In Ruby's core library, yes. It's possible to implement new methods with similar behavior
> (which is occasionally useful), but that isn't the norm.

For example:

class Person
attr_accessor :name, :age
def initialize( name )
@name = name
@age = 0
end
def grow_older
@age += 1
end
end

def create( name, &block )
person = Person.new( name )
person.instance_eval( &block )
p person
end

create( :gavin ){
@age = 32
grow_older
}
#=> #<Person:0x28347c4 @age=33, @name=:gavin>



Using instance eval makes some DSLs (domain specific languages) easier
to create, rather than having to use the object yielded to the block
in every call. Compare the usage of 'create' above to this usage:

def create( name )
person = Person.new( name )
yield person
p person
end

create( :gavin ){ |person|
person.age = 32
person.grow_older
}
#=> #<Person:0x28347c4 @age=33, @name=:gavin>


Gavin Kistner

5/10/2007 10:56:00 PM

0

On May 10, 4:50 pm, Phrogz <g...@refinery.com> wrote:
> Using instance eval makes some DSLs (domain specific languages) easier
> to create, rather than having to use the object yielded to the block
> in every call.

Here's a real-world example of a DSL I created at work:

bp( 9 ){
lopa( '02' ){
sb "New Project Workflow.ppt"
cr 1331

sb "Add to Online Repository.ppt"
crs 2216, 3560
keywords "Workspace", "Phase 2"
}
}

For both blocks, the function creates an instance of a particular
class and then uses instance_eval to ensure that the methods
referenced within that block are called on the appropriate object. If
I had not mucked about with the self inside the blocks, I would have
had to write something like:

bp( 9 ){ |blockpoint|
blockpoint.lopa( '02' ){ |section|
section.sb "New Project Workflow.ppt"
section.cr 1331

section.sb "Add to Online Repository.ppt"
section.crs 2216, 3560
section.keywords "Workspace", "Phase 2"
}
}

Vasco Andrade e silva

5/11/2007 12:12:00 AM

0

I agree with you (Gavin Kistner). The question is, what could you loose
if self was always set as it is with class_eval, instance_eval, etc.?
You could still do:
>def create( name )
> person = Person.new( name )
> yield person
> p person
>end
>
>create( :gavin ){ |person|
> person.age = 32
> person.grow_older
>}
as all the other things.

For me the question is: What's the purpose of not always setting self to
yield context?

Vasco A. Silva

--
Posted via http://www.ruby-....

dblack

5/11/2007 12:15:00 AM

0