Рубиновый многострочный блок без конца - PullRequest
19 голосов
/ 09 сентября 2010

Я новичок в Ruby, поэтому прошу прощения за что-то столь простое, но есть ли что-то не так с этим кодом -

3.upto(9) {
  print "Hello"
  puts " World"
}

или

3.upto(9) { |n|
  print "Hello "
  puts n
}

Это работает достаточно хорошо, но большинство примеров кода, которые я вижу, используют синтаксис

3.upto(9) do |n|
  print "Hello "
  puts n
end

это просто соглашение использовать только фигурные скобки для отдельных операторов? Исходя из C / C # первое кажется мне более естественным, но когда в Риме!

Ответы [ 3 ]

43 голосов
/ 10 сентября 2010

Существует небольшая разница между двумя синтаксисами.{ } имеет более высокий приоритет, чем do ... end.Таким образом, следующее передаст bar и блок методу foo:

foo bar do ... end

, в то время как следующее передаст блок к bar, а результат этого к foo:

foo bar { ... }

Так что ваши примеры будут действовать так же.Однако, если вы оставили скобки:

> 3.upto 9 { 
  puts "Hi" 
}
SyntaxError: compile error
(irb):82: syntax error, unexpected '{', expecting $end
3.upto 9 { 
          ^
    from (irb):82
    from :0

> 3.upto 9 do 
    puts "Hi" 
  end
Hi
Hi
Hi
Hi
Hi
Hi
Hi
=> 3

Итак, { } с большей вероятностью вас настигнет, если вы оставите скобки в Ruby, что довольно часто;по этой причине и поскольку все условные выражения Ruby и другие управляющие конструкции используют end в качестве разделителя, люди обычно используют do ... end для многострочных блоков кода, которые идут в конце оператора.

Однако,{ } часто используется в тех местах, где do ... end будет громоздким, например, если вы объединяете несколько методов, которые принимают блоки.Это может позволить вам записывать короткие однострочные маленькие блоки, которые можно использовать как часть цепочки методов.

> [1,2,3].sort{|x,y| y<=>x}.map{|x| x+1}
=> [4, 3, 2]

Вот пример, иллюстрирующий эту разницу:

def foo arg
  if block_given?
    puts "Block given to foo"
    yield arg
  else
    puts "No block given to foo"
    arg
  end
end


def bar
  if block_given?
    puts "Block given to bar"
    yield "Yielded from bar"
  else
    puts "No block given to bar"
  end
  "Returned from bar"
end

irb(main):077:0> foo bar { |arg| puts arg }
Block given to bar
Yielded from bar
No block given to foo
=> "Returned from bar"
irb(main):078:0> foo bar do |arg| puts arg end
No block given to bar
Block given to foo
Returned from bar
=> nil
7 голосов
/ 09 сентября 2010

Это просто соглашение.

0 голосов
/ 18 октября 2017

Там бесшовные . Из README:

Python позволяет сигнализировать конец блока кода с отступом. Ruby страдает от чрезвычайно многословного и утомительного терминатора блока, «конца». Подобно тому, как в Лиспе заканчиваются десятки близких паренов, файлы Ruby, в которых используются модули и классы, в конечном итоге заканчиваются множеством «концов», которые просто не нужны.

Написать Ruby-файл, но пропустить все «концы». Выстраивайте свои блоки кода, как в Python. Затем просто назовите его «your_file.rbe», требуйте «seamless» и «your_file». Бесшовные делает все остальное.

Должно ли это когда-либо широко использоваться? Я не знаю. Но это довольно весело!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...