Sig
Sig

Reputation: 5948

Passing a block as keyword argument

Is it possible (if yes how) to pass a block as a keyword argument in a ruby method?

Basically, I'd like to do

pippo(even: {|n| n+1 }, odd: {|n| n-1})

Having the method defined as such

def pippo(even: , odd:)
  even? ? even.yield(self) : odd.yield(self)
end

Thanks

Upvotes: 3

Views: 1529

Answers (2)

Jörg W Mittag
Jörg W Mittag

Reputation: 369458

No, this is not possible. Blocks aren't objects, you can't pass them as arguments, except as block arguments. They are a lightweight syntactic and semantic construct that is only allowed as a block argument to a message send. The light weight of blocks is predicated on the fact that there can be at most one block, and thus it doesn't need to be named and/or bound to a parameter.

What you can do, however, is pass multiple Procs or lambdas. After all, Procs and lambdas are objects like any other object, so you can pass them as arguments like any other object:

pippo(even: -> n { n+1 }, odd: -> n { n-1 })

def pippo(even: , odd:)
  if even? then even.(self) else odd.(self) end
end

Actually, this allows you to pass any object which responds to call, e.g. a Method:

pippo(even: 1.method(:+), odd: 1.method(:-))

Upvotes: 5

tadman
tadman

Reputation: 211590

If you want to supply multiple blocks you need to pass them through as a Proc, or use the lambda construct to declare them:

when(
  even: -> (x) { x+1 },
  odd: -> (x) { x-1 }
)

You can also declare them using proc { ... } or lambda { ... } which is the old style declaration for same.

Upvotes: 4

Related Questions