Ruby: A function returning another function - ruby

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.

Related

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.

What do you call the -> operator in Ruby?

What do you call the -> operator as in the following?
->(...) do
...
end
Aren't the following snippets equivalent?
succ = ->(x) {x + 1}
succ = lambda {|x| x + 1}
In Ruby Programming Language ("Methods, Procs, Lambdas, and Closures"), a lambda defined using -> is called lambda literal.
succ = ->(x){ x+1 }
succ.call(2)
The code is equivalent to the following one.
succ = lambda { |x| x + 1 }
succ.call(2)
Informally, I have heard it being called stabby lambda or stabby literal.
=> == Hash Rocket
Separates keys from values in a hash map literal.
-> == Dash Rocket
Used to define a lambda literal in Ruby 1.9.X (without args) and Ruby 2.X (with args). The examples you give (->(x) { x * 2 } & lambda { |x| x * 2 }) are in fact equivalent.
->(x) { ... } is the same as lambda { |x| ... }. It creates a lambda. See Kernel#lambda A lambda is a type of proc, one that ensures the number of parameters passed to it is correct. See also Proc::new and Kernel#proc.

How do I deep copy a Proc in 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.

conditional chaining in ruby

Is there a good way to chain methods conditionally in Ruby?
What I want to do functionally is
if a && b && c
my_object.some_method_because_of_a.some_method_because_of_b.some_method_because_of_c
elsif a && b && !c
my_object.some_method_because_of_a.some_method_because_of_b
elsif a && !b && c
my_object.some_method_because_of_a.some_method_because_of_c
etc...
So depending on a number of conditions I want to work out what methods to call in the method chain.
So far my best attempt to do this in a "good way" is to conditionally build the string of methods, and use eval, but surely there is a better, more ruby, way?
You could put your methods into an array and then execute everything in this array
l= []
l << :method_a if a
l << :method_b if b
l << :method_c if c
l.inject(object) { |obj, method| obj.send(method) }
Object#send executes the method with the given name. Enumerable#inject iterates over the array, while giving the block the last returned value and the current array item.
If you want your method to take arguments you could also do it this way
l= []
l << [:method_a, arg_a1, arg_a2] if a
l << [:method_b, arg_b1] if b
l << [:method_c, arg_c1, arg_c2, arg_c3] if c
l.inject(object) { |obj, method_and_args| obj.send(*method_and_args) }
You can use tap:
my_object.tap{|o|o.method_a if a}.tap{|o|o.method_b if b}.tap{|o|o.method_c if c}
Sample class to demonstrate chaining methods that return a copied instance without modifying the caller.
This might be a lib required by your app.
class Foo
attr_accessor :field
def initialize
#field=[]
end
def dup
# Note: objects in #field aren't dup'ed!
super.tap{|e| e.field=e.field.dup }
end
def a
dup.tap{|e| e.field << :a }
end
def b
dup.tap{|e| e.field << :b }
end
def c
dup.tap{|e| e.field << :c }
end
end
monkeypatch: this is what you want to add to your app to enable conditional chaining
class Object
# passes self to block and returns result of block.
# More cumbersome to call than #chain_if, but useful if you want to put
# complex conditions in the block, or call a different method when your cond is false.
def chain_block(&block)
yield self
end
# passes self to block
# bool:
# if false, returns caller without executing block.
# if true, return result of block.
# Useful if your condition is simple, and you want to merely pass along the previous caller in the chain if false.
def chain_if(bool, &block)
bool ? yield(self) : self
end
end
Sample usage
# sample usage: chain_block
>> cond_a, cond_b, cond_c = true, false, true
>> f.chain_block{|e| cond_a ? e.a : e }.chain_block{|e| cond_b ? e.b : e }.chain_block{|e| cond_c ? e.c : e }
=> #<Foo:0x007fe71027ab60 #field=[:a, :c]>
# sample usage: chain_if
>> cond_a, cond_b, cond_c = false, true, false
>> f.chain_if(cond_a, &:a).chain_if(cond_b, &:b).chain_if(cond_c, &:c)
=> #<Foo:0x007fe7106a7e90 #field=[:b]>
# The chain_if call can also allow args
>> obj.chain_if(cond) {|e| e.argified_method(args) }
Although the inject method is perfectly valid, that kind of Enumerable use does confuse people and suffers from the limitation of not being able to pass arbitrary parameters.
A pattern like this may be better for this application:
object = my_object
if (a)
object = object.method_a(:arg_a)
end
if (b)
object = object.method_b
end
if (c)
object = object.method_c('arg_c1', 'arg_c2')
end
I've found this to be useful when using named scopes. For instance:
scope = Person
if (params[:filter_by_age])
scope = scope.in_age_group(params[:filter_by_age])
end
if (params[:country])
scope = scope.in_country(params[:country])
end
# Usually a will_paginate-type call is made here, too
#people = scope.all
Use #yield_self or, since Ruby 2.6, #then!
my_object.
then{ |o| a ? o.some_method_because_of_a : o }.
then{ |o| b ? o.some_method_because_of_b : o }.
then{ |o| c ? o.some_method_because_of_c : o }
Here's a more functional programming way.
Use break in order to get tap() to return the result. (tap is in only in rails as is mentioned in the other answer)
'hey'.tap{ |x| x + " what's" if true }
.tap{ |x| x + "noooooo" if false }
.tap{ |x| x + ' up' if true }
# => "hey"
'hey'.tap{ |x| break x + " what's" if true }
.tap{ |x| break x + "noooooo" if false }
.tap{ |x| break x + ' up' if true }
# => "hey what's up"
Maybe your situation is more complicated than this, but why not:
my_object.method_a if a
my_object.method_b if b
my_object.method_c if c
I use this pattern:
class A
def some_method_because_of_a
...
return self
end
def some_method_because_of_b
...
return self
end
end
a = A.new
a.some_method_because_of_a().some_method_because_of_b()
If you're using Rails, you can use #try. Instead of
foo ? (foo.bar ? foo.bar.baz : nil) : nil
write:
foo.try(:bar).try(:baz)
or, with arguments:
foo.try(:bar, arg: 3).try(:baz)
Not defined in vanilla ruby, but it isn't a lot of code.
What I wouldn't give for CoffeeScript's ?. operator.
I ended up writing the following:
class Object
# A naïve Either implementation.
# Allows for chainable conditions.
# (a -> Bool), Symbol, Symbol, ...Any -> Any
def either(pred, left, right, *args)
cond = case pred
when Symbol
self.send(pred)
when Proc
pred.call
else
pred
end
if cond
self.send right, *args
else
self.send left
end
end
# The up-coming identity method...
def itself
self
end
end
a = []
# => []
a.either(:empty?, :itself, :push, 1)
# => [1]
a.either(:empty?, :itself, :push, 1)
# => [1]
a.either(true, :itself, :push, 2)
# => [1, 2]

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