开发者

Ruby lambda arguments

This code works as expected (does nothing, even doesn't produce warning/errors):

l = lambda {|i|}
l.call(1)

This code produces warning (warning: multiple values for a block parameter (0 for 1)):

l = lambda {|i|}
l.call

And this code fails with error (ArgumentError: wrong number of arguments (0 for 2)):

l = lambda {|i, y|}
l.call

I thought that lambda requires all argument to be passed.

And from the second example I see that it isn't. Why does it work when only one argument is given, and works as expected (fails with error) with more than one argument?

PS: ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]

UPDATE: I've checked these samples with ruby 1.9.1p376. And it works as expected - the second example also produces an error. Looks like开发者_运维知识库 this is a feature of 1.8 version (or <=1.8)


Lambdas are weird like that, their behavior is different when you have less than two arguments. Check this article for more information.


This script will teach you everything you need to know about closures in Ruby.

# So, what's the final verdict on those 7 closure-like entities?          
#
#                                                     "return" returns from closure
#                                    True closure?    or declaring context...?         Arity check?
#                                    ---------------  -----------------------------    -------------------
# 1. block (called with yield)       N                declaring                        no
# 2. block (&b => f(&b) => yield)    N                declaring                        no
# 3. block (&b => b.call)            Y except return  declaring                        warn on too few
# 4. Proc.new                        Y except return  declaring                        warn on too few
# 5. proc                                    <<< alias for lambda in 1.8, Proc.new in 1.9 >>>
# 6. lambda                          Y                closure                          yes, except arity 1
# 7. method                          Y                closure                          yes


When a lambda expects arguments and we don't provide them, or we provide the wrong number of arguments, an exception is thrown.

l = lambda { |name| puts "Today we will practice #{name} meditation." }
l.call
ArgumentError: wrong number of arguments (given 0, expected 1)

We can use the arity method to find out the number of expected arguments:

l.arity  # Output: => 1

Just like methods, lambdas accept all of the following types of parameters/arguments:

  • Positional parameters (required and optional)
  • Single splat parameter (*);
  • Keyword parameters (required and optional);
  • Double splat parameter (**);
  • Explicit block parameter prefixed with ampersand (&).

The following examples illustrate the syntax of a lambda that takes multiple types of arguments.

# Stabby syntax
l = -> (cushion, meditation="kinhin", *room_items, time:, posture: "kekkafuza", **periods, &p) do
  p.call
end

# Regular syntax
l = lambda do |cushion, meditation="kinhin", *room_items, time:, posture:     "kekkafuza", **periods, &p|
  p.call
end

l.call("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon" ) { puts "Hello from inside the block, which is now a proc." }

Output:
Hello from inside the block, which is now a proc.

Lambdas handle arguments the same way as methods. There is a comprehensive explanation of all the above parameter/argument types in this blog post about methods.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜