# Accessing instance vars in a block?

**URL:** <https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337>\
**Category:** Ruby\
**Created:** [November 4, 2006, 8:24pm UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337 "2006-11-04T20:24:10Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 4, 2006, 8:24pm UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/1 "2006-11-04T20:24:10Z")

</div>

I’m using rmagick:

img.write(self.path) { self.quality = @quality }

@quality is nil inside the block. How can I access its value inside the  
block? I saw there’s apparently a “variable” keyword, but that causes an  
error:

img.write(self.path) {  
variable @quality  
self.quality = @quality  
}

Thanks,  
Joe

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 4, 2006, 8:50pm UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/2 "2006-11-04T20:50:23Z")

</div>

This works but…yuck!

$q = @quality

img.write(self.path) { self.quality = $q }

Joe

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:02am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/3 "2006-11-07T11:02:00Z")

</div>

On Nov 4, 2006, at 11:24 AM, Joe R. MUDCRAP-CE wrote:

> img.write(self.path) {  
> variable @quality  
> self.quality = @quality  
> }
> 
> Thanks,  
> Joe

```
It looks like maybe ImageMagick is using instance_eval inside that

```

block. This is why the @instance vars don’t work inside of there. The  
ugly workaround is to use local variables:

quality = @quality  
img.write(self.path) { self.quality = quality }

Cheers

– Ezra Z.  
– Lead Rails Evangelist  
– removed\_email\_address@domain.invalid  
– Engine Y., Serious Rails Hosting  
– (866) 518-YARD (9273)

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:03am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/4 "2006-11-07T11:03:32Z")

</div>

Ezra Z. wrote:

> block. This is why the @instance vars don’t work inside of there. The  
> ugly workaround is to use local variables:
> 
> quality = @quality  
> img.write(self.path) { self.quality = quality }

Hmm. This might have been brought up before, but blocks seem rather  
underpowered with respects to manipulating them? A way to prevent their  
binding scope from being clobbered by using them in an instance\_eval  
context would be nifty. Or having nested block bindings depending on use

- so if this block got instance\_eval’ed twice inside RMagick, it would  
look up read variable references in all the scopes that apply, last  
object first. With the interpreter looking for and reporting possible  
conflicts as a warning when those are allowed (not otherwise, that  
sounds like a horrid performance hit without any sort of code path  
inference to optimize the detection process.) Of course, this might  
still be a problem with autovivification of instance variables

Of course, this would probably do Cruel and Unusual Things ™ to block  
performance, and it’s possible to mitigate the problem by always  
documenting what methods rescope their block argument, and then users  
actually reading the documentation.  
([RMagick 1.15.0: class Image (instance methods, part 3)](http://www.simplesystems.org/RMagick/doc/image3.html#write) does state  
the block sets attributes on another object.)

Of course, that necessitates still the Javascripty hack of reassigning  
stuff to instance variables - personally I think instance\_eval’ing an  
external block is a hideous practice that violates encapsulation with  
gay abandon, and therefore shouldn’t -ever- be used across the library /  
client boundary. In this case, I’d go the way of yielding the  
Image::Info object to the block, even if that robs you of the novel and  
exciting feeling of having direct access to a library’s unmentionables  
as the common case instead of the special one.

David V.

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:02am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/5 "2006-11-07T11:02:31Z")

</div>

Joe R. MUDCRAP-CE wrote:

> This works but…yuck!  
> $q = @quality  
> img.write(self.path) { self.quality = $q }

No reason to use a global. Use a local variable as Ezra suggested.

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:03am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/6 "2006-11-07T11:03:54Z")

</div>

removed\_email\_address@domain.invalid wrote:

> how the method works. I don’t think it would be good to try to figure  
> out where the block came from and set up some mechanism that way.  
> That goes against the grain of having first-class closures at all.

My point is that with instance\_eval, the block doesn’t close over its  
lexical scope as is most often expected, but over the instance scope of  
another object. At least it seems that way to me. It might be useful,  
but it’s an inconsistency that a library can force on its client. The  
whole proposal at first was a longshot, and sort of a workaround against  
flaky API design.

> I think one just has to hope people won’t do the “stealth”  
> instance\_eval. If they do, you’d presumably know about it from the  
> docs, and can avoid it.

Which is why I’d prefer that libraries don’t do this at all in their  
API. It seems like a code / design smell to me to make part of your  
object internals part of your API, and there are less iffy ways of  
exposing part of your object conditionally - e.g. dynamically defining  
extra singleton accessors for the attributes you want the block to have  
access to before yielding the object to the block as a regular parameter  
and undefining them afterwards. And in the RMagick example, I have  
slight doubts that for any and all practical reasons and purposes,  
having the Image::Info object as a block parameter to Image#write  
instead of using instance\_eval would be any different except that it  
would surprise users less.

David V.

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:03am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/7 "2006-11-07T11:03:37Z")

</div>

Hi –

On Sun, 5 Nov 2006, David V. wrote:

> Hmm. This might have been brought up before, but blocks seem rather  
> underpowered with respects to manipulating them? A way to prevent their  
> binding scope from being clobbered by using them in an instance\_eval  
> context would be nifty.

But instance\_eval takes a block; it’s not a special context, but just  
how the method works. I don’t think it would be good to try to figure  
out where the block came from and set up some mechanism that way.  
That goes against the grain of having first-class closures at all.

I think one just has to hope people won’t do the “stealth”  
instance\_eval. If they do, you’d presumably know about it from the  
docs, and can avoid it.

David

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:04am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/8 "2006-11-07T11:04:57Z")

</div>

Wilson B. wrote:

> > actually reading the documentation.
> 
> This is basically just a Ruby implementation problem. I’m reading  
> through the Smalltalk ‘Blue Book’ now, and it shows that it is  
> possible to have blocks that are ‘real’ objects while still offering  
> very high performance.  
> This is something we can fix with hard work on the Ruby internals.

Actually, not really. Smalltalk didn’t have eval. The very prospect that  
a Ruby block could call eval on any arbitrary text means you can’t, in  
the general case, discard a block’s binding (the biggest benefit to ST  
block performance was saving yourself closing over the lexical scope  
whenever possible) - and either way eval is a general nuisance to  
optimise without Dark Magic. In Ruby, IIRC, the performance hit of  
constructing the equivalent of a ST full block is worked around by the  
duality of “real” and “fake” blocks - the fake ones don’t need being  
constructed as objects because their lexical scope is still on the  
interpreter stack. Coincidentally, since “real” blocks are always full  
blocks in the ST sense of the term, they’re also a yummy inherent memory  
leak.

(Someone with more intimate knowledge on Ruby internals might correct me  
on the above.)

It’s probably possible to apply some heuristics to try to see if this  
might happen as an optimization, but Ruby is a far more complex language  
than ST (alias, dynamic requires of source files, eval, constant lookup  
to name a few features Blue Book ST didn’t have), and reasoning about  
behaviour of Ruby code algorithmically is much harder. So, while it is  
probably possible, I wouldn’t expect this to happen anytime soon - it’s  
a price you pay for the flexibility and metaprogramming convenience.

Personally, I’d be in favour of either being able to optionally disable  
eval in the interpreter if that is in fact the language feature that  
makes fast clean blocks impossible (it might be only partially guilty)  
and making the standard library eval-free to comply with that.  
Alternately, introducing keywords / methods to let a programmer manually  
declare which blocks do not reference enclosing locals or the enclosing  
object to hand-optimize could work also. (This should be done on  
creation, discarding a binding -after- the object is created wouldn’t do  
anything for performance, even if it would solve the memory leak  
issues.)

David V.

---

<div class="post-metadata">

**Author:** ![joe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/b9e5f3/32.png) [@joe](https://www.ruby-forum.com/u/joe)\
**Post date:** [November 7, 2006, 11:04am UTC](https://www.ruby-forum.com/t/accessing-instance-vars-in-a-block/74337/9 "2006-11-07T11:04:47Z")

</div>

On 11/5/06, David V. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hmm. This might have been brought up before, but blocks seem rather  
> underpowered with respects to manipulating them?
> 
> Of course, this would probably do Cruel and Unusual Things ™ to block  
> performance, and it’s possible to mitigate the problem by always  
> documenting what methods rescope their block argument, and then users  
> actually reading the documentation.

This is basically just a Ruby implementation problem. I’m reading  
through the Smalltalk ‘Blue Book’ now, and it shows that it is  
possible to have blocks that are ‘real’ objects while still offering  
very high performance.  
This is something we can fix with hard work on the Ruby internals.
