help with tricky proc/binding issue

A

Ara.T.Howard

i'm trying to be able to define a proc that can be called in the context of
self, eg:

block = lambda{ p 42 }
an_obj.instance_eval &block

but which can also be called with arguments, for example (imaginary ruby):

b = lambda{|x| p [x, y]}

class C
def y; 42; end
end

c = C::new
x = 42

c.arg_instance_eval(x, &b) #=> [42, 42]

any ideas?

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: help with tricky proc/binding issue"

|i'm trying to be able to define a proc that can be called in the context of
|self, eg:
|
| block = lambda{ p 42 }
| an_obj.instance_eval &block
|
|but which can also be called with arguments, for example (imaginary ruby):

I understand what you want. But I haven't come up with a good name
for the function yet.

matz.
 
R

Robert Klemme

Ara.T.Howard said:
i'm trying to be able to define a proc that can be called in the
context of self, eg:

block = lambda{ p 42 }
an_obj.instance_eval &block

but which can also be called with arguments, for example (imaginary
ruby):

b = lambda{|x| p [x, y]}

class C
def y; 42; end
end

c = C::new
x = 42

c.arg_instance_eval(x, &b) #=> [42, 42]

any ideas?

The only workaround that comes to mind is to pass self explicitely along
with other arguments. Or use a trick with delegation that allows to do
instance_eval on a proxy self that will also provide arguments given.

robert
 
A

Ara.T.Howard

Hi,

In message "Re: help with tricky proc/binding issue"

|i'm trying to be able to define a proc that can be called in the context of
|self, eg:
|
| block = lambda{ p 42 }
| an_obj.instance_eval &block
|
|but which can also be called with arguments, for example (imaginary ruby):

I understand what you want. But I haven't come up with a good name
for the function yet.

maybe

class Object
def evaluate(*args, &block)
...
end
end

??

another option would be to turn the problem inside out and do something like

l = lambda{ p x }
l.self = obj
l.call


this is what i have so far:

[ahoward@localhost ~]$ cat a.rb
class Object
def evaluate(*a, &b)
m = "____eval____#{ rand(65536) }____"
klass = Class === self ? self : self::class
klass.module_eval{ define_method m, &b }
begin
send m, *a
ensure
klass.module_eval{ remove_method m }
end
end
end

class C
def y
42
end
end

b = lambda{|x| p [x, y, self]}

c = C::new
x = 42
c.evaluate(x, &b) #=> [42, 42, #<C:0xb7f2f5c0>]


[ahoward@localhost ~]$ ruby a.rb
[42, 42, #<C:0xb7f1b5c0>]


thoughts?

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
P

Pit Capitain

Ara.T.Howard said:
i'm trying to be able to define a proc that can be called in the context of
self, eg:

block = lambda{ p 42 }
an_obj.instance_eval &block

but which can also be called with arguments, for example (imaginary ruby):

b = lambda{|x| p [x, y]}

class C
def y; 42; end
end

c = C::new
x = 42

c.arg_instance_eval(x, &b) #=> [42, 42]

any ideas?

Tom (aka Trans) recently mentioned that he changed procs into methods in
order to get what you want. Here's a quick hack, not efficient and not
thread-safe, but maybe a start:

class Object
def arg_instance_eval( *args, &block )
c = class << self; self; end
c.send( :define_method, :arg_instance_eval_method, &block )
arg_instance_eval_method( *args )
ensure
c.send( :remove_method, :arg_instance_eval_method )
end
end

b = lambda{|x| p [x, y]}

class C
def y; 42; end
end

c = C::new
z = 41

c.arg_instance_eval( z, &b ) # => [41, 42]

Regards,
Pit
 
F

Florian Groß

Ara.T.Howard said:
i'm trying to be able to define a proc that can be called in the context of
self, eg:

block = lambda{ p 42 }
an_obj.instance_eval &block

but which can also be called with arguments, for example (imaginary ruby):

Currently the only way of doing this is Proc#self= from evil.rb...
 
F

Florian Groß

Yukihiro said:
|i'm trying to be able to define a proc that can be called in the context of
|self, eg:
|
| block = lambda{ p 42 }
| an_obj.instance_eval &block
|
|but which can also be called with arguments, for example (imaginary ruby):

I understand what you want. But I haven't come up with a good name
for the function yet.

What about Proc#with_self() that will return a new proc similar to the
current one, but with a changed self context?
 
F

Florian Groß

Ara.T.Howard said:
another option would be to turn the problem inside out and do something
like

l = lambda{ p x }
l.self = obj
l.call

Procs are currently immutable and I'd assume that the source code
assumes that they can not be changed in several places. It's less risky
to return a new object with a changed self context, IMHO.
 
R

Robert Klemme

Pit said:
Ara.T.Howard said:
i'm trying to be able to define a proc that can be called in the
context of self, eg:

block = lambda{ p 42 }
an_obj.instance_eval &block

but which can also be called with arguments, for example (imaginary
ruby):

b = lambda{|x| p [x, y]}

class C
def y; 42; end
end

c = C::new
x = 42

c.arg_instance_eval(x, &b) #=> [42, 42]

any ideas?

Tom (aka Trans) recently mentioned that he changed procs into methods
in order to get what you want. Here's a quick hack, not efficient and
not thread-safe, but maybe a start:

class Object
def arg_instance_eval( *args, &block )
c = class << self; self; end
c.send( :define_method, :arg_instance_eval_method, &block )
arg_instance_eval_method( *args )
ensure
c.send( :remove_method, :arg_instance_eval_method )
end
end

Hacky but nice! For thread safety how about:

class Object
def arg_instance_eval( *args, &block )
c = class << self; self; end
meth = "__m_#{Thread.current.object_id}_#{rand 666}"
c.send( :define_method, meth, &block )
send( meth, *args )
ensure
c.send( :remove_method, meth )
end
end

Kind regards

robert
 
M

Martin DeMello

Florian Groß said:
Procs are currently immutable and I'd assume that the source code
assumes that they can not be changed in several places. It's less risky
to return a new object with a changed self context, IMHO.

proc.bound_to(object), perhaps.

martin
 
A

Ara.T.Howard

any ideas?

Tom (aka Trans) recently mentioned that he changed procs into methods in
order to get what you want. Here's a quick hack, not efficient and not
thread-safe, but maybe a start:

class Object
def arg_instance_eval( *args, &block )
c = class << self; self; end
c.send( :define_method, :arg_instance_eval_method, &block )
arg_instance_eval_method( *args )
ensure
c.send( :remove_method, :arg_instance_eval_method )
end
end

b = lambda{|x| p [x, y]}

class C
def y; 42; end
end

c = C::new
z = 41

c.arg_instance_eval( z, &b ) # => [41, 42]

that's funny. here's my current hack:

class Object
def evaluate(*a, &b)
ret, sent = nil
loop do
m = "____evaluate____#{ rand(42) }____#{ rand(42) }____"
klass = Class === self ? self : self::class
begin
klass.module_eval{ define_method m, &b }
ret = send(sent = m, *a)
ensure
begin
klass.module_eval{ remove_method m }
ensure
break if sent
end
end
end
ret
end
end

class C
def y
42
end
end

b = lambda{|x| p [x, y, self]}

c = C::new
x = 42
c.evaluate(x, &b) #=> [42, 42, #<C:0xb7f2f5c0>]

guess that's the way to go for now.


cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
A

Ara.T.Howard

Hacky but nice! For thread safety how about:

class Object
def arg_instance_eval( *args, &block )
c = class << self; self; end
meth = "__m_#{Thread.current.object_id}_#{rand 666}"
^^^
^^^
^^^

lol! ;-)

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
A

Ara.T.Howard

Hacky but nice! For thread safety how about:
<snip>


what i think to be the final version:

class Object
def evaluate(*a, &b)
ret, sent = nil
loop do
m = "____evaluate____#{ Thread::current.object_id }____#{ rand 666 }____#{ rand 42 }____"
klass = Class === self ? self : self::class
begin
klass.module_eval{ define_method m, &b }
ret = send(sent = m, *a)
ensure
begin
klass.module_eval{ remove_method m }
ensure
break if sent
end
end
end
ret
end
end

class C
def y
42
end
end

b = lambda{|x| p [x, y, self]}

c = C::new
x = 42
c.evaluate(x, &b) #=> [42, 42, #<C:0xb7f2f5c0>]


-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
E

Eric Mahurin

--- Florian Gro=DF said:
Yukihiro Matsumoto wrote:
=20
=20
What about Proc#with_self() that will return a new proc
similar to the=20
current one, but with a changed self context?

I've talked about this before, but the ability to return a new
proc with local variables manipulated would also be nice:

- Make "local" variables really local to the proc. Initialize
these to the current values of the local variables in the
previous binding. Effectively, this gives the proc its own
local binding (at least for "local" variables). This could be
done in conjunction with redefining self for the proc to.

It would also be nice to be able to be able to do the same
thing for blocks easily so that you could easily localize your
"local" variables in your block. But, you could emulate that
as long as you had a way to localize proc local variables:

foo(&(lambda{...}.localize))

or if you could do it directly to a block you may have some
syntax like this:

foo {{...}} # double braces to represent localization

But, that has some conflicts with hash. Not sure of a good
syntax. The problem is we can't apply methods directly to
blocks - you have to convert to Proc, apply the method, and
convert back.


__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top