Define anonymous module with closure

Hi everyone,

I want to do this:

x, y = %w(x y)
definition = lambda{def z; x; end}
y.extend Module.new(&definition)
y.z # => ‘x’

I expected x to be available within the closure, but it doesn’t appear
to be. The only way I’ve found is with module_eval:

x, y = %w(x y)
mod = Module.new
mod.module_eval “def z; #{x.inspect}; end”
y.extend mod
y.z # => ‘x’

Which I guess is fine, but I’m opposed to eval, and especially
eval’ing strings, on principle.

So:

Why doesn’t the first option work? I saw something somewhere about the
argument to Module::new being called within some other scope/context/
whatsit?

Is there a way to do this without eval?

Thanks!
-Ian

On Sep 16, 2008, at 1:17 PM, I. E. Smith-Heisters wrote:

x, y = %w(x y)
definition = lambda{def z; x; end}
y.extend Module.new(&definition)
y.z # => ‘x’

cfp:~ > cat a.rb
x, y = %w( x y )

definition = lambda{ define_method(:z){ x } }

y.extend Module.new(&definition)

p y.z # => ‘x’

cfp:~ > ruby a.rb
“x”

‘def’ creates a new scope - you lose the closure surrounding ‘x’. to
keep it use ‘define_method’, which takes a block - aka closure.

a @ http://codeforpeople.com/

On Sep 16, 12:46 pm, “ara.t.howard” [email protected] wrote:

definition = lambda{ define_method(:z){ x } }

a @http://codeforpeople.com/

we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama

brilliant! thanks for the explanation and solution all in one.

Ara Howard wrote:

cfp:~ > ruby a.rb
“x”
you need to do it this way if you want your method to take a block

…if you are constrained to 1.8.6.

% ruby --version
ruby 1.8.7 (2008-08-11 patchlevel 72)

class A
define_method(:f) { |x, &block|
puts “A#f argument: #{x}”
block.call(88)
}
end

A.new.f(99) { |t|
puts “block called with: #{t}”
}

=> A#f argument: 99

block called with: 88

Now if you want default parameters, you’ll need Ara’s example again.
Unless you use 1.9…

% ruby --version
ruby 1.9.0 (2008-09-15 revision 19346)

class A
t = ->(a = 11, b = 22) { a + b }
define_method(:g, &t)
end

a = A.new
p a.g # => 33
p a.g(33) # => 55
p a.g(33, 44) # => 77

From what I gathered, -> was introduced because

lambda { |a = 11, b = 22| a + b }

was too difficult or ambiguous to parse. My feeling is that -> should
be avoided if at all possible, no matter how difficult.

To me, -> is a step toward ruby jumping the shark. I want to yell,
“Fonzie, don’t do it!” (Excuse the Americanisms.)

On Sep 16, 2008, at 2:17 PM, I. E. Smith-Heisters wrote:

brilliant! thanks for the explanation and solution all in one.

np. if you need a block then:

cfp:~ > cat a.rb
x, y = %w( x y )

m = Module.new do
@@x = x

def z *args, &block
block.call if block
@@x
end
end

y.extend m

p y.z # => ‘x’

y.z{ puts ‘you need to do it this way if you want your method to take
a block’ }

cfp:~ > ruby a.rb
“x”
you need to do it this way if you want your method to take a block

a @ http://codeforpeople.com/