How do I deep copy a Proc in Ruby? - ruby

Is there a straightforward way in Ruby to produce a copy of a Proc?
I have a Proc called #foo. I want another method to periodically augment #foo with additional logic. For example:
# create initial Proc
#foo = lambda { |x| x }
# augment with more logic
#foo = lambda { |x| x > 1 ? x*x : #foo[x] }
I don't want the second line that does the augmentation to produce a recursive function. Instead, I want #foo to be bound by value into the lexical scope of the new #foo definition, producing a function that looks more like this:
#foo = lambda { |x| x > 1 ? x*x : lambda{ |x| x }[x] }
I get an infinite recursion and an eventual stack overflow instead, due to the resulting function looking like this:
#foo = lambda { |x| x > 1 ? x*x : lambda { |x| x > 1 ? x*x : { lambda |x| # etc...
I'd like the code to be like this:
# augment with more logic
#foo = lambda { |x| x > 1 ? x*x : (#foo.clone)[x] }
but clone doesn't work on Procs.
Additionally, the standard Ruby deep copy hack, using marshal and unmarshal, doesn't work on Procs either. Is there some way to do this?

Even if clone would work on Procs, it wouldn't help you, because you'd still be calling clone on the new value of #foo, not on the previous one like you want.
What you can do instead is just store the old value of #foo in a local variable that the lambda can close over.
Example:
def augment_foo()
old_foo = #foo
#foo = lambda { |x| x > 1 ? x*x : old_foo[x] }
end
This way old_foo will refer to the value that #foo had when augment_foo was called and everything will work as you want.

Related

How can I create an enumerator that does certain things after iteration?

How can I create an enumerator that optionally takes a block? I want some method foo to be called with some arguments and an optional block. If it is called with a block, iteration should happen on the block, and something should be done on it, involving the arguments given. For example, if foo were to take a single array argument, apply map on it with the given block, and return the result of join applied to it, then it would look like:
foo([1, 2, 3]){|e| e * 3}
# => "369"
If it is called without a block, it should return an enumerator, on which instance methods of Enumerator (such as with_index) should be able to apply, and execute the block in the corresponding way:
enum = foo([1, 2, 3])
# => Enumerator
enum.with_index{|e, i| e * i}
# => "026"
I defined foo using a condition to see if a block is given. It is easy to implement the case where the block is given, but the part returning the enumerator is more difficult. I guess I need to implement a sublass MyEnum of Enumerator and make foo return an instance of it:
def foo a, &pr
if pr
a.map(&pr).join
else
MyEnum.new(a)
end
end
class MyEnum < Enumerator
def initialize a
#a = a
...
end
...
end
But calling MyEnum.new raises a warning message: Enumerator.new without a block is deprecated; use Object#to_enum. If I use to_enum, I think it would return a plain Enumerator instance, not the MyEnum with the specific feature built in. On top of that, I am not sure how to implement MyEnum in the first place. How can I implement such enumerator? Or, what is the right way to do this?
You could do something like this.
def foo a, &pr
if pr
a.map(&pr).join
else
o = Object.new
o.instance_variable_set :#a, a
def o.each *y
foo #a.map { |z| yield z, *y } { |e| e }
end
o.to_enum
end
end
Then we have
enum = foo([1,2,3])
enum.each { |x| 2 * x } # "246"
or
enum = foo([1,2,3])
enum.with_index { |x, i| x * i } # "026"
Inspiration was drawn from the Enumerator documentation. Note that all of your expectations about enumerators like you asked for hold, because .to_enum takes care of all that. enum is now a legitimate Enumerator!
enum.class # Enumerator

Ruby: A function returning another function

In order to understand the functional programming part of ruby I want to write a function that takes 2 functions f(x,y),g(x) as arguments and returns a new function h(x,y)=f(g(x),g(y)).
def foo(x, y)
return x+y
end
def bar(x)
return 2*x
end
def comp(f,g)
end
f=comp(f,g)
f(1,2) #=> 6
I tried things like
def comp(f,g)
mylambda = lambda {|x,y| return f(g(x),g(y))}
return mylambda
end
f=comp(foo, bar)
f.call(1,2)
I thought f would be a Proc now, and I could just call it. But apparently "in `foo': wrong number of arguments (0 for 2) (ArgumentError)"
What syntax would I have to use? And is it possible to return a "real" function instead of a Proc, so that instead of f.call(1,2) I could just writhe f(1,2) like if I had just defined f myself normaly?
This type of functional pattern doesn't work as smoothly as on more functional languages, as javascript or python. Since ruby has optional parentheses, writing foo is the same as calling the foo method without passing any arguments.
To get a reference to a method, you need to use the Object#method method:
def foo(x, y)
x + y
end
def bar(x)
x * 2
end
def comp(f, g)
lambda { |x, y| f.call(g.call(x), g.call(y)) }
end
h = comp(method(:foo), method(:bar))
h.call(1, 2) # => 6
Ruby doesn't have first class functions like Python. Ruby has lambdas, and method objects that can be constructed specially from a method, but methods themselves are not objects. The closest you'll get to this is this:
def foo(x, y)
return x+y
end
def bar(x)
return 2*x
end
def comp(f,g)
return lambda {|x, y| f.call(g.call(x), g.call(y))}
end
f=comp(method(:f),method(:g))
f.call(1,2) #=> 6
Also, for the calling syntax point, you can call a lambda with square brackets, so you could do this:
f[1,2]
What you have there aren't functions, they are methods. Functions (more precisely: procedures) are defined like this:
foo = -> (x, y) { x + y }
bar = -> x { 2 * x }
comp = -> (f, g) { -> (x, y) { f.(g.(x), g.(y)) } }
f = comp.(foo, bar)
f.(1, 2) #=> 6
Try this:
def foo() lambda {|x,y| x+y} end
def bar() lambda {|x| 2*x} end
def comp(f,g) lambda {|x,y| f[g[x], g[y]]} end
h = comp(foo, bar)
h[1,2] # => 6
or any of the following
h.call(1,2) # => 6
h.(1,2) # => 6
h.yield(1,2) # => 6
If you'd prefer,
foo = lambda {|x,y| x+y}
bar = lambda {|x| 2*x}
Before this question I was unaware of the myriad of ways one can now invoke a lambda (or proc). (The rationale for providing Proc#yield escapes me, as it is the same as call and may be confused with the unrelated yield keyword we all know and love.) One could substitute Proc.new or proc for lambda, or create the lambda with the "stabby" syntax -> (e.g., def bar() ->(x) {2*x} end.
f=comp(foo, bar)
This won't work like it would in python. The error message you're getting is wanting to see something like this.
f = comp(foo(1,2), bar(1))
You need to actually make foo and bar lambdas themselves (or methods that return lambdas) if you want to call it like that:
foo = lambda { |x, y| x + y }
bar = lambda { |x| 2 * x }
or
def foo(x, y)
lambda { |x, y| x + y}
end
def bar(x)
lambda { |x| 2 * x }
end
Then you can achieve what you want to do.

Pass parameters to passed-in block in Ruby

I want to pass a block to a function, and then call that block with some additional parameters as follows:
def foo(&block)
some_array = (1..3).to_a
x = 7 # Simplified
result = some_array.map &block # Need some way to pass in 'x' here
end
def a_usage_that_works
foo do |value|
value
end
end
def a_usage_that_doesnt_work
foo do |value, x|
x # How do I pass in x?
end
end
# rspec to demonstrate problem / required result
describe "spike" do
it "works" do
a_usage_that_works.should == [1,2,3]
end
it "doesn't work" do
a_usage_that_doesnt_work.should == [7, 7, 7]
end
end
How can I pass in the additional parameter to the block?
Create another block and call first one from it.
def foo(&block)
some_array = (1..3).to_a
x = 7 # Simplified
result = some_array.map {|elem| block.call(elem, x)}
end
You pass to the block by yielding to it.
def foo(&block)
some_array = [1,2,3]
x = 7
some_array.map{|el| yield el, x}
end
p foo{|p1, p2| p2} #=>[7,7,7]
p foo{|p1, p2| p1} #=>[1,2,3]
You can use a higher-order function to generate a simplified function:
Let's assume that the block we pass to foo will accept value, x.
Naive strategy, using an inline-defined x:
def foo(&block)
some_array = (1..3).to_a
x = 7
simple_func = proc {|value| block.call(value, x) }
result = some_array.map &simple_func
end
Strategy using separation of concerns:
def get_simple_func(block)
# This assumes x won't change per iteration.
# If it can change, you can move the calculation inside the proc.
# Moving it inside also allows the calculation to depend on "value", in case you want that.
x = complex_calculation_for_x()
proc {|value| block.call(value, x) }
end
def foo(&block)
some_array = (1..3).to_a
simple_func = get_simple_func(block)
result = some_array.map &simple_func
end
Obviously you shouldn't use this when x is a literal value because it would be over-engineering. But as the calculation of x becomes more complex, separating it out makes the code more readable. Also, foo can focus on the specific task of applying the function to some_array.

How to implement an enumerator in Ruby?

For example:
a = [1,2,3,4,5]
a.delete_if { |x| x > 3 }
is equivalent to:
a = [1,2,3,4,5]
a.delete_if.each.each.each.each { |x| x > 3 }
I know a.delete_if returns an enumerator. But how does it know it should delete object when the each block returns true? How to implement delete_if by hand(and in Ruby)?
You can take a look at the Rubinius source code: enumerable module
Here an example of the reject method:
def reject
return to_enum(:reject) unless block_given?
ary = []
each do |o|
ary << o unless yield(o)
end
ary
end
In the implementation of delete_if, the code can verify the value returned from yield to decide whether or not to delete the given entry from the array.
You can read Implementing Iterators in the Programming Ruby guide for more details, but it would looks something like:
class Array
def delete_if
reject { |i| yield i }.to_a
end
end
The above uses yield to pass each item in the array to the block associated with the call to delete_if, and implicitly returns the value of the yield to the outer reject call.

How do you stringize/serialize Ruby code?

I want to be able to write a lambda/Proc in my Ruby code, serialize it so that I can write it to disk, and then execute the lambda later. Sort of like...
x = 40
f = lambda { |y| x + y }
save_for_later(f)
Later, in a separate run of the Ruby interpreter, I want to be able to say...
f = load_from_before
z = f.call(2)
z.should == 42
Marshal.dump does not work for Procs. I know Perl has Data::Dump::Streamer, and in Lisp this is trivial. But is there a way to do it in Ruby? In other words, what would be the implementation of save_for_later?
Edit: My answer below is nice, but it does not close over free variables (like x) and serialize them along with the lambda. So in my example ...
x = 40
s = save_for_later { |y| x + y }
# => "lambda { |y|\n (x + y)\n}"
... the string output does not include a definition for x. Is there a solution that takes this into account, perhaps by serializing the symbol table? Can you access that in Ruby?
Edit 2: I updated my answer to incorporate serializing local variables. This seems acceptable.
Use Ruby2Ruby
def save_for_later(&block)
return nil unless block_given?
c = Class.new
c.class_eval do
define_method :serializable, &block
end
s = Ruby2Ruby.translate(c, :serializable)
s.sub(/^def \S+\(([^\)]*)\)/, 'lambda { |\1|').sub(/end$/, '}')
end
x = 40
s = save_for_later { |y| x + y }
# => "lambda { |y|\n (x + y)\n}"
g = eval(s)
# => #<Proc:0x4037bb2c#(eval):1>
g.call(2)
# => 42
This is great, but it does not close over free variables (like x) and serialize them along with the lambda.
To serialize variables also, you can iterate over local_variables and serialize them as well. The problem, though, is that local_variables from within save_for_later accesses only c and s in the code above -- i.e. variables local to the serialization code, not the caller. So unfortunately, we must push the grabbing of local variables and their values to the caller.
Maybe this is a good thing, though, because in general, finding all free variables in a piece of Ruby code is undecidable. Plus, ideally we would also save global_variables and any loaded classes and their overridden methods. This seems impractical.
Using this simple approach, you get the following:
def save_for_later(local_vars, &block)
return nil unless block_given?
c = Class.new
c.class_eval do
define_method :serializable, &block
end
s = Ruby2Ruby.translate(c, :serializable)
locals = local_vars.map { |var,val| "#{var} = #{val.inspect}; " }.join
s.sub(/^def \S+\(([^\)]*)\)/, 'lambda { |\1| ' + locals).sub(/end$/, '}')
end
x = 40
s = save_for_later(local_variables.map{ |v| [v,eval(v)] }) { |y| x + y }
# => "lambda { |y| _ = 40; x = 40;\n (x + y)\n}"
# In a separate run of Ruby, where x is not defined...
g = eval("lambda { |y| _ = 40; x = 40;\n (x + y)\n}")
# => #<Proc:0xb7cfe9c0#(eval):1>
g.call(2)
# => 42
# Changing x does not affect it.
x = 7
g.call(3)
# => 43
Use sourcify
This will work on Ruby 1.8 or 1.9.
def save_for_later(&block)
block.to_source
end
x = 40
s = save_for_later {|y| x + y }
# => "proc { |y| (x + y) }"
g = eval(s)
# => #<Proc:0x00000100e88450#(eval):1>
g.call(2)
# => 42
See my other answer for capturing free variables.
Update:
Now you can also use the serializable_proc gem, which uses sourcify, and captures local, instance, class, and global variables.
Check out the answers to this question.
Ruby has the Marshal class that has a dump method that you can call.
Take a look here:
http://rubylearning.com/satishtalim/object_serialization.html

Resources