How to indent if…any…do…end…end [closed]

白昼怎懂夜的黑 提交于 2019-12-23 04:33:08

问题


I am new to ruby and I wonder how you would indent this code:

if a.any? do |blah|
name = blah[:name][/.* (.*)/, 1]
name = convert_name(name)
text = "#{name}#{blah[:value]}"
text == "b2"
end
puts "found"
exit 1
end

回答1:


I'd write it something like:

if a.any? { |blah| (blah[:name] + blah[:value]) == "b2" }
  puts "found"
  exit 1
end

Or:

if a.any? { |blah| blah.values_at(:name, :value).join == "b2" }
  puts "found"
  exit 1
end

The actual test is short enough that it can be done in a single line.

Generally we use braces ({}) for blocks when they return a value or are on a single line.

Interpolating two strings in another string just to join them is smelly. Just concatenate them; It's more obvious what you're doing.


If you're ONLY concerned about how to indent clearly, consider this:

if a.any? do |blah|
    name = blah[:name][/.* (.*)/, 1]
    name = convert_name(name)
    text = "#{name}#{blah[:value]}"
    text == "b2"
  end
  puts "found"
  exit 1
end

The any? block should be indented further than the contents of the if block to visually separate them. Beyond the indention... ugh... the code block for any? should be refactored to a single line still.




回答2:


Like so:

if(a.any? { |blah| text = "#{blah[:name]}#{blah[:value]}"; text == "b2"})
  puts "found"
  exit 1
end

If your any? block is really long, do this:

result = a.any? do |blah| 
  text = "#{blah[:name]}#{blah[:value]}"
  text == "b2"
  ...
end
if(result)
  puts "found"
  exit 1
end



回答3:


I'd probably toss the search logic into a lambda:

are_wanted = lambda do |blah|
  name = blah[:name][/.* (.*)/, 1]
  name = convert_name(name)
  text = "#{name}#{blah[:value]}"
  text == "b2"
end

Then once it has a name so that we can tell what it is for at a glance, the if becomes nice and readable:

if a.any?(&are_wanted)
  puts "found"
  exit 1
end

I find this technique quite useful when you end up with a complicated Enumerable pipeline, things like this for example:

pull_em_apart        = lambda { ... }
the_good_ones        = lambda { ... }
put_em_back_together = lambda { ... }
array.map(&pull_em_apart)
     .select(&the_good_ones)
     .map(&put_em_back_together)

when the lambdas are more than a single line are a lot easier to understand than a big mess of inlined blocks.




回答4:


Part of the challenge is to cleanly accommodate both the if and any? blocks, since both terminate with an end. One way to distinguish between them, then, is to use braces for the inner block, to make it clearer what is going on:

if a.any? { |blah|
    name = blah[:name][/.* (.*)/, 1]
    name = convert_name(name)
    text = "#{name}#{blah[:value]}"
    text == "b2" }
then
  puts "found"
  exit 1
end

Thanks Cary Swoveland for suggesting the then.




回答5:


Another choice:

begin
  puts "found"
  exit 1
end if a.any? do |blah|
  name = blah[:name][/.* (.*)/, 1]
  name = convert_name(name)
  text = "#{name}#{blah[:value]}"
  text == "b2"
end


来源:https://stackoverflow.com/questions/21193057/how-to-indent-if-any-do-end-end

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!