Ruby's scoping rules with respect to iterators are kinda controversial even by the standards of other languages with lexical scoping. (In Lisp you'd be able to look at the parentheses and know exactly what's in scope where! :) There's been talk of changing them but I'm not 1.9- savvy enough to know if any of that has happened yet.

The reason is that when iterators were conceived, they were thought of as abbreviated, glorified "for" loops, but it soon became apparent that having an easy way to pass a block to a method allowed you to do all kinds of wonderful unforeseen things, and they became a major feature of Ruby -- but there were some historical artifacts regarding scoping, from their more humble origins, that seem peculiar in retrospect.

That's what I vaguely remember hearing about it anyway. I could be wrong and welcome correction!

On Jul 27, 2009, at 5:42 AM, Cecil Coupe wrote:

Yet another reminder why Lisp scoping rules and my feeble lexical brain don't mesh. I have no opinion as to why or if it's a good thing (Tm) but
it'll burn us old school non Lispers.

On Mon, 2009-07-27 at 05:15 -0400, MenTaLguY wrote:
I wasn't terribly clear.  Let me rephrase -- if you do this:

urls.each do |url|
  link url, :click => Proc.new { window { image url } }
end

Then every link will open the same image url (since all the created
Procs reference the same variable, which ends up with the same final
value).  However, if you do this:

def make_image_callback(url)
  Proc.new { window { image url } }
end

image_urls.each do |image_url|
  link image_url, :click => make_image_callback(image_url)
end

Then the links should open the correct images, since each call to
make_image_callback establishes up a separate context for a Proc inside
to capture, rather than all the Procs sharing the same context and
variables.

You could also do the call to link itself inside the helper method (as I
did in my earlier email), but you don't need to.

-mental



Reply via email to