2016-03-15 2 views
2

Я попытался сделать глупый пример, чтобы получить представление о нескольких процедурах, переданных методу. Однако одна вещь, которая меня поразила, - это порядок исполнения. Я посмотрел документацию Proc, но на самом деле не нашел объяснений (возможно, я не смотрел достаточно внимательно).Порядок выполнения для нескольких процедур в Ruby

Вот пример:

def my_block(a, b) 
    a.call b.call 
end 

a = Proc.new { puts "hello" } 
b = Proc.new { puts " world" } 

my_block a, b 

Выход:

world 
hello 

Похоже, что исполнение Proc когда дано больше, чем один на линии выполняет слева направо. Может кто-нибудь объяснить это поведение в деталях?

+0

Это на самом деле очень интересно. Теперь я пытаюсь понять, почему это происходит! – dane

+0

Спасибо @dane. Оцените любую помощь или ввод. ':)' –

+0

Возможно, мне казалось, что компилятор смещает «<<» их в массив, так как они находятся на одной строке, а затем b.call на самом деле получает ontop? @jaypal sigh – dane

ответ

3

Это потому, что это:

a.call b.call 

действительно:

a.call(b.call()) 

Так b.call() получает расширен (и запустить) первым, как и в любой ПР»язык программирования, и результат от этого передается как параметр до a.

Вы хотели бы надеяться, что это даст ошибку, но в Ruby, дополнительный параметр в блоке не приводит к ошибкам (это ошибка для метода, однако) ...

Вы можете использовать точку с запятой явно сказать рубин, чтобы начать новое выражение:

a.call; b.call 

... но я бы сказал, что это довольно unidiomatic и «не-Рубин» ...

+0

Спасибо за объяснение! Трудно понять дополнительные параны, когда вы едете из java! ':)' –

+1

@jaypalsingh, если вам интересно, почему вы не видите ошибку, это потому, что 'call' получает переменный параметр или любое количество аргументов. В этом случае он ничего не делает с ними. – Mohamad

+0

Спасибо за редактирование. ', но в дополнительном параметре Ruby для блока не приводят к ошибкам', это важная нота для учета. –

2

Это просто потому, что у вас есть они оба на одной линии, поэтому b.call вызывается как параметр для a.call. Чтобы это работало так, как вы ожидаете, вам нужно;

def my_block(a, b) 
    a.call 
    b.call 
end 
+0

да теперь, когда я вижу, вы правы! Спасибо – dane

+0

Спасибо @ james2m! –

Смежные вопросы