2015-03-01 5 views
1

Я занимаюсь курсом по изучению Ruby. Все идет хорошо, за исключением того, что я не могу окунуться в это поведение блока.Смутно о поведении блоков в Ruby

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 

Код, который не проходит:

def adder(x) 
    yield + x 
end 

другой код, который не проходит:

def adder x 
    x = 1 
    yield + x 
end 

код, который проходит:

def adder x = 1 
    yield + x 
end 

Для меня оба непереходящих кода имеют логический смысл. Я пробовал искать в Интернете по той причине, что последний проходит, а другие нет, но мне не повезло. Может ли кто-нибудь объяснить, почему?

спасибо.

ответ

3

Есть несколько проблем,

В первом примере, «х» не имеет значения по умолчанию, поэтому он не будет автоматически увеличивать его на единицу. Он должен пройти, если вы передадите 1 в качестве аргумента.

adder(1) do 
    5 
end 

вернется 6. Он должен пройти второй тест, но не первый.

Во втором примере 'x' будет установлен в 1 независимо от того, что передал аргумент, поэтому второй тест всегда терпит неудачу - он принимает аргумент и сразу же игнорирует его. Это означает, что он пройдет для первого теста, но не второго.

В третьем примере оно принимает значение по умолчанию для x, но переназначает его, если аргумент передан, поэтому он передает оба теста.

3

Для первого и второго методов x не имеет значения по умолчанию в объявлении метода. Первый тест не поставил бы один, подняв ArgumentError.

Третий способ включает значение по умолчанию для x в объявлении метода, позволяющее ему вызывать с 0 или 1 аргументом. И adder (по умолчанию 1) и adder(2) в равной степени действительны.

0

Прежде всего, should api устарел в rspec 3, вместо этого вы должны использовать expect. первое определение метода не проходит, потому что метод adder ожидает аргумент, но первый пример спецификации не проходит.

второе определение не передает второй пример, поскольку оно игнорирует переданный аргумент.

третье определение является правильным в данном случае, потому что, если абонент не передать аргумент, x принимает значение по умолчанию 1, но если он передает аргумент, чем параметр x будет принимать это значение. и, таким образом, оба примера пройдут.