# Passing math method to another method?

Discussion in 'Ruby' started by Neutek, Jan 17, 2007.

1. ### NeutekGuest

I'm trying to figure out how to pass methods such as:
+, -, **, ^
to a method and evaluate.

For example,

def test(a, b, to_do)
return a.send(to_do(b))
end

puts test(1, 2, "+") #should return 3
puts test(3, 3, "^") #should return 0
puts test(3, 3, "**") #should return 27

any help would be appreciated.

Neutek, Jan 17, 2007

2. ### James Edward Gray IIGuest

On Jan 17, 2007, at 8:10 AM, Neutek wrote:

> I'm trying to figure out how to pass methods such as:
> +, -, **, ^
> to a method and evaluate.
>
> For example,
>
> def test(a, b, to_do)
> return a.send(to_do(b))
> end
>
>
> puts test(1, 2, "+") #should return 3
> puts test(3, 3, "^") #should return 0
> puts test(3, 3, "**") #should return 27
>
> any help would be appreciated.

>> def test(a, b, meth)
>> a.send(meth, b)
>> end

=> nil
>> test(1, 2, :+)

=> 3
>> test(3, 3, :^)

=> 0
>> test(3, 3, :**)

=> 27

Hope that helps.

James Edward Gray II

James Edward Gray II, Jan 17, 2007

3. ### Xavier NoriaGuest

On Jan 17, 2007, at 3:10 PM, Neutek wrote:

> I'm trying to figure out how to pass methods such as:
> +, -, **, ^
> to a method and evaluate.
>
> For example,
>
> def test(a, b, to_do)
> return a.send(to_do(b))
> end
>
>
> puts test(1, 2, "+") #should return 3
> puts test(3, 3, "^") #should return 0
> puts test(3, 3, "**") #should return 27

a.send(to_do, b)

Xavier Noria, Jan 17, 2007
4. ### Rob BiedenharnGuest

On Jan 17, 2007, at 9:10 AM, Neutek wrote:

> I'm trying to figure out how to pass methods such as:
> +, -, **, ^
> to a method and evaluate.
>
> For example,
>
> def test(a, b, to_do)
> return a.send(to_do(b))
> end
>
>
> puts test(1, 2, "+") #should return 3
> puts test(3, 3, "^") #should return 0
> puts test(3, 3, "**") #should return 27
>
> any help would be appreciated.

You're very close:

>> def test(a, b, to_do)
>> a.send(to_do, b)
>> end

=> nil
>> test(1, 2, "+")

=> 3
>> test(3, 3, '^')

=> 0
>> test(3, 3, '**')

=> 27

Rob Biedenharn http://agileconsultingllc.com

Skype: rob.biedenharn

Rob Biedenharn, Jan 17, 2007
5. ### Robert KlemmeGuest

On 17.01.2007 15:06, Neutek wrote:
> I'm trying to figure out how to pass methods such as:
> +, -, **, ^
> to a method and evaluate.
>
> For example,
>
> def test(a, b, to_do)
> return a.send(to_do(b))
> end
>
>
> puts test(1, 2, "+") #should return 3
> puts test(3, 3, "^") #should return 0
> puts test(3, 3, "**") #should return 27
>
> any help would be appreciated.

Several ways to do it

irb(main):001:0> def test(a,b,op) a.send(op,b) end
=> nil
irb(main):002:0> test 1,2,:"+"
=> 3
irb(main):003:0> def test(a,b,op) a.send(op.to_sym,b) end
=> nil
irb(main):004:0> test 1,2,"+"
=> 3
irb(main):005:0> def test(a,b,op) op[a,b] end
=> nil
irb(main):006:0> test 1,2,lambda {|x,y| x+y}
=> 3

The last sample shows the more functional approach.

What are you trying to achieve?

Kind regards

robert

Robert Klemme, Jan 17, 2007
6. ### Kalman NoelGuest

Robert Klemme:
> irb(main):003:0> def test(a,b,op) a.send(op.to_sym,b) end

^^^^^^
> => nil
> irb(main):004:0> test 1,2,"+"
> => 3

Any specific reason for to_sym's appearing there?

Kalman

Kalman Noel, Jan 17, 2007
7. ### NeutekGuest

Wow. Thanks for the input guys.

Robert, I was actually reading the summation wiki and they had a few
code examples in C++/Java.. I thought I'd goof a bit and write
something out in ruby. Of course, I hit the roadblock when trying to
pass math operators(or methods rather) to a method...

I got this far ;-)

def sigma(floor, to_do, cap)

end
puts sigma(4, ^2, 20)

I will fiddle with your suggestions and continue with my sigma

Thanks again for all your help

Robert Klemme wrote:
> On 17.01.2007 15:06, Neutek wrote:
> > I'm trying to figure out how to pass methods such as:
> > +, -, **, ^
> > to a method and evaluate.
> >
> > For example,
> >
> > def test(a, b, to_do)
> > return a.send(to_do(b))
> > end
> >
> >
> > puts test(1, 2, "+") #should return 3
> > puts test(3, 3, "^") #should return 0
> > puts test(3, 3, "**") #should return 27
> >
> > any help would be appreciated.

>
> Several ways to do it
>
> irb(main):001:0> def test(a,b,op) a.send(op,b) end
> => nil
> irb(main):002:0> test 1,2,:"+"
> => 3
> irb(main):003:0> def test(a,b,op) a.send(op.to_sym,b) end
> => nil
> irb(main):004:0> test 1,2,"+"
> => 3
> irb(main):005:0> def test(a,b,op) op[a,b] end
> => nil
> irb(main):006:0> test 1,2,lambda {|x,y| x+y}
> => 3
>
> The last sample shows the more functional approach.
>
> What are you trying to achieve?
>
> Kind regards
>
> robert

Neutek, Jan 17, 2007
8. ### Robert KlemmeGuest

** SPOILER **

Don't read on if you first want to experiment yourself.

On 17.01.2007 17:48, Neutek wrote:
> Robert, I was actually reading the summation wiki and they had a few
> code examples in C++/Java.. I thought I'd goof a bit and write
> something out in ruby. Of course, I hit the roadblock when trying to
> pass math operators(or methods rather) to a method...

http://en.wikipedia.org/wiki/Sum

If yes, here are some more ways:

# plain values
sum = (m..n).inject(0){|s,x| s + x}

# with a function
f = lambda {|i| i * 2}
sum = (m..n).inject(0){|s,x| s + f[x]}

# in a method
def sum(m, n, f)
(m..n).inject(0){|s,x| s + f[x]}
end

s = sum( 1, 2, lambda {|x| x * 2} )

etc.

Advantage of using lambdas is that they are more flexible than method
names and can contain arbitrary calculations.

Kind regards

robert

Robert Klemme, Jan 17, 2007
9. ### Robert KlemmeGuest

On 17.01.2007 17:47, Kalman Noel wrote:
> Robert Klemme:
>> irb(main):003:0> def test(a,b,op) a.send(op.to_sym,b) end

> ^^^^^^
>> => nil
>> irb(main):004:0> test 1,2,"+"
>> => 3

>
> Any specific reason for to_sym's appearing there?

Yes, my ignorance.

robert

Robert Klemme, Jan 17, 2007
10. ### NeutekGuest

Robert Klemme wrote:
> ** SPOILER **
>
> Don't read on if you first want to experiment yourself.
>
>
> On 17.01.2007 17:48, Neutek wrote:
> > Robert, I was actually reading the summation wiki and they had a few
> > code examples in C++/Java.. I thought I'd goof a bit and write
> > something out in ruby. Of course, I hit the roadblock when trying to
> > pass math operators(or methods rather) to a method...

>
> What is the "summation wiki"? Are you referring to this page?
> http://en.wikipedia.org/wiki/Sum
>
> If yes, here are some more ways:
>
> # plain values
> sum = (m..n).inject(0){|s,x| s + x}
>
> # with a function
> f = lambda {|i| i * 2}
> sum = (m..n).inject(0){|s,x| s + f[x]}
>
> # in a method
> def sum(m, n, f)
> (m..n).inject(0){|s,x| s + f[x]}
> end
>
> s = sum( 1, 2, lambda {|x| x * 2} )
>
> etc.
>
> Advantage of using lambdas is that they are more flexible than method
> names and can contain arbitrary calculations.
>
> Kind regards
>
> robert
>
>
> PS: Please don't top post.

What's top post? (sorry, I'm new to google groups --I put my reply at
the bottom if this is what you meant )

I'll read through your example now but figured what I worked on in the
interim was worth posting..

#works
def test(a, to_do, b)
return a.send(to_do, b)
end
puts test(2, :**, 3)

#does not work when trying to send an entire mathematical expresion as
a param
def sigma(floor, to_do, cap)
x = 0
floor.upto(cap) {|i|
x += i.send(to_do)
}
return x
end
puts sigma(4, :**2, 20)

#does not work.. but another example of what I would expect

def do_it(n, to_do)
return n.send(to_do)
end
puts sigma(3, :+4/2) #should yield 5

(Thank you)²

Neutek, Jan 17, 2007
11. ### NeutekGuest

Cool... I think this works

#does not work when trying to send an entire mathematical expresion as
a param
def sigma(floor, to_do, cap)
x = 0
floor.upto(cap) {|i|
#x += i.send(to_do)
x += to_do
}
return x
end
puts sigma(4, lambda{|x| x ** 2}, 20)

Thanks a million!

Neutek wrote:
> Robert Klemme wrote:
> > ** SPOILER **
> >
> > Don't read on if you first want to experiment yourself.
> >
> >
> > On 17.01.2007 17:48, Neutek wrote:
> > > Robert, I was actually reading the summation wiki and they had a few
> > > code examples in C++/Java.. I thought I'd goof a bit and write
> > > something out in ruby. Of course, I hit the roadblock when trying to
> > > pass math operators(or methods rather) to a method...

> >
> > What is the "summation wiki"? Are you referring to this page?
> > http://en.wikipedia.org/wiki/Sum
> >
> > If yes, here are some more ways:
> >
> > # plain values
> > sum = (m..n).inject(0){|s,x| s + x}
> >
> > # with a function
> > f = lambda {|i| i * 2}
> > sum = (m..n).inject(0){|s,x| s + f[x]}
> >
> > # in a method
> > def sum(m, n, f)
> > (m..n).inject(0){|s,x| s + f[x]}
> > end
> >
> > s = sum( 1, 2, lambda {|x| x * 2} )
> >
> > etc.
> >
> > Advantage of using lambdas is that they are more flexible than method
> > names and can contain arbitrary calculations.
> >
> > Kind regards
> >
> > robert
> >
> >
> > PS: Please don't top post.

>
> What's top post? (sorry, I'm new to google groups --I put my reply at
> the bottom if this is what you meant )
>
> I'll read through your example now but figured what I worked on in the
> interim was worth posting..
>
>
> #works
> def test(a, to_do, b)
> return a.send(to_do, b)
> end
> puts test(2, :**, 3)
>
> #does not work when trying to send an entire mathematical expresion as
> a param
> def sigma(floor, to_do, cap)
> x = 0
> floor.upto(cap) {|i|
> x += i.send(to_do)
> }
> return x
> end
> puts sigma(4, :**2, 20)
>
>
> #does not work.. but another example of what I would expect
>
> def do_it(n, to_do)
> return n.send(to_do)
> end
> puts sigma(3, :+4/2) #should yield 5
>
>
> (Thank you)²

Neutek, Jan 17, 2007
12. ### Robert KlemmeGuest

On 17.01.2007 18:21, Neutek wrote:
> Cool... I think this works
>
>
> #does not work when trying to send an entire mathematical expresion as
> a param
> def sigma(floor, to_do, cap)
> x = 0
> floor.upto(cap) {|i|
> #x += i.send(to_do)
> x += to_do
> }
> return x
> end
> puts sigma(4, lambda{|x| x ** 2}, 20)
>
> Thanks a million!

Basically if you think this further through, what you are trying to do
is already part of Ruby's standard lib. The method is #inject. I think
I used it in one of my postings. Your piece above becomes

puts (4..20).inject(0) {|s,x| s + x ** 2}

or, to more directly translate using #upto

require 'enumerator'
puts 4.to_enumupto, 20).inject(0) {|s,x| s + x ** 2}

Cheers

robert

Robert Klemme, Jan 18, 2007