I've got a bit of a problem whereby I need to pass a block to a method
defined using define_method this works:
def some_method(*args, &block)
# ...
end
but this does not -- the interpreter complains about unexpected ampersands:
define_method(:some_method) do |*args, &block|
# ...
end
Is there any way to make this work? I'm doing something a little meta, so I
don't know the name of the method or the number of arguments, so it's all
got to be dynamic.
I've got a bit of a problem whereby I need to pass a block to a method
defined using define_method this works:
def some_method(*args, &block)
# ...
end
but this does not -- the interpreter complains about unexpected ampersands:
define_method(:some_method) do |*args, &block|
# ...
end
Is there any way to make this work? I'm doing something a little meta, so I
don't know the name of the method or the number of arguments, so it's all
got to be dynamic.
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
I've got a bit of a problem whereby I need to pass a block to a method
defined using define_method this works:
def some_method(*args, &block)
# ...
end
but this does not -- the interpreter complains about unexpected ampersands:
define_method(:some_method) do |*args, &block|
# ...
end
Is there any way to make this work? I'm doing something a little meta, so I
don't know the name of the method or the number of arguments, so it's all
got to be dynamic.
--
James Coglan
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
I'm actually wrapping existing methods so I need to use define_method to
retain access to the old method. Here's my (broken) code so far:
module Continuations
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
define_method(method_name) do |*params, &block|
value = func.bind(self).call(*params)
end
end
end
end
define_method "__call__#{method_name}" do |b, *a|
begin
m.bind(self).call(*a, &b)
ensure
p :WRAPPED!
end
end
eval <<-EOF
def #{method_name} *a, &b
__call__#{method_name}(b, *a)
end
EOF
- steve
···
On Tue, Aug 26, 2008 at 10:28 PM, ara.t.howard <ara.t.howard@gmail.com>wrote:
On Aug 26, 2008, at 8:30 AM, James Coglan wrote:
Hi list,
I've got a bit of a problem whereby I need to pass a block to a method
defined using define_method this works:
def some_method(*args, &block)
# ...
end
but this does not -- the interpreter complains about unexpected
ampersands:
define_method(:some_method) do |*args, &block|
# ...
end
Is there any way to make this work? I'm doing something a little meta, so
I
don't know the name of the method or the number of arguments, so it's all
got to be dynamic.
def accepts_continuation *argv
argv.flatten.compact.each do |arg|
arg = arg.to_s
klass = Class === self ? self : self.class
Funcs[arg] = klass.send(:instance_method, arg)
klass.module_eval <<-code
def #{ arg }(*a, &b)
Continuations.funcs[#{ arg.inspect }].bind(self).call(*a, &b)
ensure
STDERR.puts 'wrapped!'
end
code
end
end
end
def foo &b
b.call 'bar'
end
foo{|bar| puts "foo#{ bar }"}
include Continuations
accepts_continuation :foo
foo{|bar| puts "foo#{ bar }"}
cfp:~ > ruby a.rb
foobar
foobar
wrapped!
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
I'm actually wrapping existing methods so I need to use define_method to
retain access to the old method. Here's my (broken) code so far:
module Continuations
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
define_method(method_name) do |*params, &block|
value = func.bind(self).call(*params)
end
end
end
end
To clarify, this formulation does not work:
module Continuations
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
module_eval <<-EOS
def #{method_name}(*params, &block)
value = func.bind(self).call(params)
end
EOS
end
end
end
I'm actually wrapping existing methods so I need to use define_method to
retain access to the old method. Here's my (broken) code so far:
I think I saw this "trick" in one of Ara's posts
* Store the method somewhere so it is not GC by ruby
* Retrieve the method object from its object_id with ObjectSpace._id2ref
* use eval instead of define_method
module Continuations
NOGC =
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
NOGC << func # Stop garbage collection of the method.
func_object_id = func.object_id
#define_method(method_name) do |*params, &block|
# value = func.bind(self).call(*params) #end
I'm actually wrapping existing methods so I need to use define_method to
retain access to the old method. Here's my (broken) code so far:
module Continuations
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
define_method(method_name) do |*params, &block|
value = func.bind(self).call(*params)
end
end
end
end
In Ruby 1.9 you can do this:
func = ->(*a,&block) { block.call if block; puts a }
=> #<Proc:0x388bdc@(irb):1 (lambda)>
C = Class.new { define_method(:hi, &func) }
=> C
C.new.hi(10) { puts "In block" }
In block
10
The ->(){} thing lets you create a lambda with method-argument
semantics.
David
···
On Wed, 27 Aug 2008, James Coglan wrote:
--
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
Advancing with Rails January 19-22 Fort Lauderdale, FL
See http://www.rubypal.com for details and updates!
I'm actually wrapping existing methods so I need to use define_method to
retain access to the old method. Here's my (broken) code so far:
module Continuations
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
define_method(method_name) do |*params, &block|
value = func.bind(self).call(*params)
end
end
end
end
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
where does the "func" method come from here? because you are
using module_eval, this is just calling a method named "func" on the
target class (the class where you included the module). I don't think
this would do what you want, even if you do have a "func" method lying
around...
I'm actually wrapping existing methods so I need to use define_method to
retain access to the old method. Here's my (broken) code so far:
module Continuations
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
define_method(method_name) do |*params, &block|
value = func.bind(self).call(*params)
end
end
end
end
In Ruby 1.9 you can do this:
func = ->(*a,&block) { block.call if block; puts a }
=> #<Proc:0x388bdc@(irb):1 (lambda)>
C = Class.new { define_method(:hi, &func) }
=> C
C.new.hi(10) { puts "In block" }
In block
10
The ->(){} thing lets you create a lambda with method-argument
semantics.
Actually the fix is in: you can now (and I think permanently) do this
in 1.9 without the ->(){}.
class C; define_method(:hi) {|*a,&block| block.call if block; puts
a }; end
=> #<Proc:0x1d5754@(irb):1 (lambda)>
C.new.hi(10) { puts "In block" }
In block
10
I'd lost track of where this stood -- I'm very glad to see that it's
there in the block syntax (thanks to Eric Mahurin's patch, if I'm not
mistaken).
David
···
On Wed, 27 Aug 2008, David A. Black wrote:
On Wed, 27 Aug 2008, James Coglan wrote:
--
Rails training from David A. Black and Ruby Power and Light:
Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
Advancing with Rails January 19-22 Fort Lauderdale, FL
See http://www.rubypal.com for details and updates!
* Store the method somewhere so it is not GC by ruby
* Retrieve the method object from its object_id with ObjectSpace._id2ref
* use eval instead of define_method
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
Just did something similar to Emmanuel's suggestion, works a treat:
module Continuations
METHODS = {}
def accepts_continuation(*args)
args.each do |method_name|
func = instance_method(method_name)
id = func.object_id
METHODS[id] = func
module_eval <<-EOS
def #{method_name}(*params, &block)
value = Continuations::METHODS[#{id}].bind(self).call(*params)
block.call(value) if block
value
end
EOS
end
end
end