Forum: Ruby Passing math method to another method?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Vrtwo L. (Guest)
on 2007-01-17 16:10
(Received via mailing list)
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.
James G. (Guest)
on 2007-01-17 16:17
(Received via mailing list)
On Jan 17, 2007, at 8:10 AM, Neutek wrote:

>
> 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 G. II
Xavier N. (Guest)
on 2007-01-17 16:18
(Received via mailing list)
On Jan 17, 2007, at 3:10 PM, Neutek wrote:

>
> 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)
Rob B. (Guest)
on 2007-01-17 16:19
(Received via mailing list)
On Jan 17, 2007, at 9:10 AM, Neutek wrote:

>
> 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 B.    http://agileconsultingllc.com
removed_email_address@domain.invalid
Skype:  rob.biedenharn
Robert K. (Guest)
on 2007-01-17 16:26
(Received via mailing list)
On 17.01.2007 15:06, Neutek wrote:
>
> 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
Vrtwo L. (Guest)
on 2007-01-17 18:51
(Received via mailing list)
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
Kalman N. (Guest)
on 2007-01-17 19:05
(Received via mailing list)
Robert K.:
> 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
Robert K. (Guest)
on 2007-01-17 19:15
(Received via mailing list)
** 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.
Robert K. (Guest)
on 2007-01-17 19:16
(Received via mailing list)
On 17.01.2007 17:47, Kalman N. wrote:
> Robert K.:
>> 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
Vrtwo L. (Guest)
on 2007-01-17 19:17
(Received via mailing list)
Robert K. wrote:
>
> sum = (m..n).inject(0){|s,x| s + f[x]}
> 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)²
Vrtwo L. (Guest)
on 2007-01-17 19:25
(Received via mailing list)
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[i]
  }
  return x
end
puts sigma(4, lambda{|x| x ** 2}, 20)

Thanks a million!
Robert K. (Guest)
on 2007-01-18 11:28
(Received via mailing list)
On 17.01.2007 18:21, Neutek wrote:
>   }
>   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_enum(:upto, 20).inject(0) {|s,x| s + x ** 2}

Cheers

  robert
This topic is locked and can not be replied to.