From: ptkwt@...1.aracnet.com (Phil Tomson) Date: 2002-04-03T06:34:01+09:00 Subject: Re: seeking to understand... In article <87hemtaotb.fsf@jenny-gnome.dyndns.org>, Yohanes Santoso wrote: >ptkwt@shell1.aracnet.com (Phil Tomson) writes: > >> Ruby has several important features lacking in Python, such as lexical >> closures. And the fact that Python just recently added iterators and > >What is this "lexical closures" that I've been hearing about? Most >probably it is something that I have been taking for granted. > >YS. A closure is a function that remembers the context in which it was created. I have to admit that while I knew this definition for a long time (they have'em in Perl too) and have looked at the examples in various books (both Perl and Ruby books) on many occasions, it wasn't until fairly recently that I had the 'AHA!' experience where I realized how useful they are. I'll try to explain the program I was working on when I had the "AHA!", but I suspect that you'll eventually have to come up with your own. My application is farily arcane: I wanted to use Ruby as a Hardware Descriptions Language (HDL). Here's a simplified example of an RHDL design: class MyDesign < RHDL::Design def initialize() a = Signal.new(1) #signals have a current value and history b = Signal.new(1) define_behavior { c.assign {a or b} } end end The line: c.assign {a + b} makes use of a closure (the '{a + b}' is a Proc object which is what Ruby calls closures). [As a side note: Signal defines an 'assign' method that takes either an immediate value or a proc.] I don't want to assign the immediate value of (a or b) to c, I want to assign the function {a or b} so that it can be calculated later with varying values for Signals a and b. Using a Proc (which, remember, is a closure) allows me to do that. The function {a or b} (NOTE: '{..}' are used to construct Procs) can then be evaluated later each time the values of a and b have been changed. The closure will be evaluated later outside of the current context, and since it carries the current lexical context around with it it's easy to do: ....later in the context of the Signal class... class Signal .... def update ... #after the procObj has been retreived from a queue: @value = procObj.call end end So given the code defined in MyDesign class above, the line: @value = procObj.call might be replaced with: @value = ( a or b ) except, you'll note that niether a or b exist in the current scope, so closures to the rescue: @value = procObj.call evaluates the function ( a or b ) in the context where it was defined in MyDesign. make sense? Phil