Passing functions as arguments to ruby

I'm trying to wrap my head in functional ruby ​​programming, and the documentation there seems to be not very good.

Essentially, I'm trying to write a union function that would have a signature like Haskell:

[a] -> [a] -> (a -> a -> a) -> [a]

So

combine([1,2,3], [2,3,4], plus_func) => [3,5,7]
combine([1,2,3], [2,3,4], multiply_func) => [2,6,12]

and etc.

I found some things about using zip and map, but it seems very ugly to use.

What would be the most “ruby” way to implement something like that?

+5
source share
4 answers

Well, you said you knew about zip and a map, so this probably doesn't help. But I will send just in case.

def combine a, b
    a.zip(b).map { |i| yield i[0], i[1] }
end

puts combine([1,2,3], [2,3,4]) { |i, j| i+j }

No, I don’t find it beautiful either.

edit - # ruby-lang @irc.freenode.net :

def combine(a, b, &block)
    a.zip(b).map(&block)
end

, :

def combine(a, b, *args, &block)
    a.zip(b, *args).map(&block)
end
+10

aproach:

def combine(a1, a2)
  i = 0
  result = []
  while a1[i] && a2[i]
    result << yield(a1[i], a2[i])
    i+=1
  end
  result
end

sum = combine([1,2,3], [2,3,4]) {|x,y| x+y}
prod = combine([1,2,3], [2,3,4]) {|x,y| x*y}

p sum, prod

=>
[3, 5, 7]
[2, 6, 12]

:

def combine(*args)
  i = 0
  result = []
  while args.all?{|a| a[i]}
    result << yield(*(args.map{|a| a[i]}))
    i+=1
  end
  result
end

EDIT: zip/map, , ?

def combine(*args)
  args.first.zip(*args[1..-1]).map {|a| yield a}
end

sum = combine([1,2,3], [2,3,4], [3,4,5]) {|ary| ary.inject{|t,v| t+=v}}
prod = combine([1,2,3], [2,3,4], [3,4,5]) {|ary| ary.inject(1){|t,v| t*=v}}
p sum, prod
+3

, Symbol.to_proc ( Raganwald)

class Symbol
  # Turns the symbol into a simple proc, which is especially useful for enumerations. 
  def to_proc
    Proc.new { |*args| args.shift.__send__(self, *args) }
  end
end

:

(1..100).inject(&:+)

: . . , , , -Ruby-like.

+1

Object#send ( Object#__send__), . (Ruby , .)

You can pass lambdaeither a block that calls your desired method according to your desired arguments. Block transfer is probably Ruby's preferred way when it works (i.e. when you only have one block to transfer).

You extract objects Methoddirectly through Object#method, and then transfer them and callthem, but I have little experience who do it this way and have not seen it done in practice.

0
source

All Articles