chrabyrd
chrabyrd

Reputation: 323

Confused about block behavior in Ruby

I'm doing a course to learn Ruby. Everything's going well except I can't wrap my head around this block behavior.

RSpec:

describe "adder" do
    it "adds one to the value returned by the default block" do
      adder do
        5
      end.should == 6
    end

    it "adds 3 to the value returned by the default block" do
      adder(3) do
        5
      end.should == 8
    end
  end

Code that doesn't pass:

def adder(x)
    yield + x
end

Another code that doesn't pass:

def adder x
    x = 1
    yield + x
end

Code that passes:

def adder x = 1
    yield + x
end

To me, both non-passing codes make logical sense. I've tried searching online for a reason the last one passes and the others don't, but I haven't had any luck. Can anyone explain why?

Thank you.

Upvotes: 1

Views: 84

Answers (3)

Nafaa Boutefer
Nafaa Boutefer

Reputation: 2359

First of all, the should api is deprecated in rspec 3, you should use expect instead. the first method definition does not pass because the adder method expect an argument, but the first spec example does not pass any.

the second definition does not pass the second example, because it ignores the argument passed.

the third definition is the correct one in this case, because if the caller does not pass an argument, x takes the default value 1, but if it passes a argument than the parameter x will take that value. and Thus both examples will pass.

Upvotes: 0

adamwellsdev
adamwellsdev

Reputation: 91

There are a couple problems,

In the first example, 'x' has no default value, so it won't automatically increment it by one. It should pass if you pass in 1 as an argument, though.

adder(1) do
  5
end

will return 6. It should be passing the second test, but failing the first.

In the second example, 'x' will be set to 1 regardless of what the argument passed in is, so the second test will always fail - it takes in an argument and then immediately disregards it. This means it will pass for the first test, but not the second.

In the third example, it takes in a default value for x, but reassigns it if an argument is passed in, so it passes both tests.

Upvotes: 3

Alexa Y
Alexa Y

Reputation: 1854

For both the first and second methods, x doesn't have a default value in the method declaration. The first test would not supply one, raising an ArgumentError.

The third method includes a default value for x in the method declaration, allowing it to be called with 0 or 1 arguments. Both adder (defaults to 1) and adder(2) are equally valid.

Upvotes: 3

Related Questions