Ruby 如何返回到调用方法?

Ruby 如何返回到调用方法?,ruby,methods,return,Ruby,Methods,Return,我有一个使用方法进行验证的程序,如果验证失败,我希望返回到调用它的方法,例如: def obtain_pokemon_name print 'Enter Pokemon: ' pokemon = gets.chomp.capitalize obtain_basic_attack(pokemon) end def obtain_basic_attack(poke) print 'Enter basic attack: ' basic_attack = gets.chomp.d

我有一个使用方法进行验证的程序,如果验证失败,我希望返回到调用它的方法,例如:

def obtain_pokemon_name
  print 'Enter Pokemon: '
  pokemon = gets.chomp.capitalize
  obtain_basic_attack(pokemon)
end

def obtain_basic_attack(poke)
  print 'Enter basic attack: '
  basic_attack = gets.chomp.downcase
  check_attacks(poke, basic_attack)
  obtain_spec_attack(poke)
end

def obtain_spec_attack(poke)
  print 'Enter special attack: '
  spec_attack = gets.chomp.downcase
  check_attacks(poke, spec_attack)
end

def check_attacks(pokemon, attack)
  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return # to where this function was called
  else
    attack
  end
end

begin
  obtain_pokemon_name
rescue => e
  puts "Failed with error code: #{e}"
end
运行此操作时:

Enter Pokemon: arbok
Enter basic attack: eat
eat is not one of Arbok's attacks, try again..
Enter special attack: test
test is not one of Arbok's attacks, try again..
攻击列表:

POKEMON_ATTACKS = {
    'Bulbasaur' => {'tackle' => 10.9, 'vine whip' => 15.4, 'power whip' => 21.4, 'seed bomb' => 12.5, 'sludge bomb' => 19.2},
    'Ivysaur' => {'razor leaf' => 10.3, 'vine whip' => 15.4, 'power whip' => 21.4, 'sludge bomb' => 19.2, 'solar beam' => 13.3},
    'Kakuna' => {'bug bite' => 13.3, 'poison sting' => 10.3, 'struggle' => 8.8},
    'Beedrill' => {'bug bite' => 13.3, 'poison jab' => 14.3, 'aerial ace' => 8.6, 'sludge bomb' => 19.2, 'x-scissor' => 14.3},
    'Pidgey' => {'quick attack' => 7.5, 'tackle' => 10.9, 'aerial ace' => 8.6, 'air cutter' => 7.6, 'twister' => 5.6},
    'Ekans' => {'acid' => 9.5, 'poison sting' => 10.3, 'gunk shot' => 20.0, 'sludge bomb' => 19.2, 'wrap' => 3.8},
    'Arbok' => {'acid' => 9.5, 'bite' => 12.0, 'dark pulse' => 12.9, 'gunk shot' => 20.0, 'sludge wave' => 17.6},
}
因此,我的问题是,如果数据中不存在攻击,如何返回调用方法?例如,如果我调用
arbok
,而他的攻击是
attack
,如果它在散列中不存在,我将如何返回到
获取基本攻击(poke)
方法?

就在这里:

   puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return # to where this function was called
您应该再次调用原始方法。i、 e

  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return obtain_spec_attack(poke)
您也可以将此逻辑添加到
获取规范\u攻击中

def obtain_spec_attack(poke)
  loop do
    print 'Enter special attack: '
    spec_attack = gets.chomp.downcase
    attack_found = check_attacks(poke, spec_attack)
    if attack_found
      break attack_found # this will return attack_found from the loop
    else
      puts "attack not found"
    end
  end
end

编辑

再看看你的问题,我意识到你想回到一个多层的方法上来。您可以使用我已经概述的方法,或者使用rescue:

def obtain_basic_attack(poke)
  begin
    print 'Enter basic attack: '
    basic_attack = gets.chomp.downcase
    check_attacks(poke, basic_attack)
    obtain_spec_attack(poke)
  rescue AttackNotFoundError
    retry # runs the 'begin' block again
  end
end

def obtain_spec_attack(poke)
  print 'Enter special attack: '
  spec_attack = gets.chomp.downcase
  check_attacks(poke, spec_attack)
end

def check_attacks(pokemon, attack)
  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    raise AttackNotFoundError
  else
    attack
  end
end
为了使用自定义错误,如
AttackNotFoundError
,您需要在某个地方定义错误类:

class AttackNotFoundError < StandardError; end
类攻击NotFoundError
您可以使用任何错误,例如
raise StandardError
,但最好限制您要挽救的错误,这样您就不会意外地挽救不相关的错误

就在这里:

   puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return # to where this function was called
您应该再次调用原始方法。i、 e

  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    return obtain_spec_attack(poke)
您也可以将此逻辑添加到
获取规范\u攻击中

def obtain_spec_attack(poke)
  loop do
    print 'Enter special attack: '
    spec_attack = gets.chomp.downcase
    attack_found = check_attacks(poke, spec_attack)
    if attack_found
      break attack_found # this will return attack_found from the loop
    else
      puts "attack not found"
    end
  end
end

编辑

再看看你的问题,我意识到你想回到一个多层的方法上来。您可以使用我已经概述的方法,或者使用rescue:

def obtain_basic_attack(poke)
  begin
    print 'Enter basic attack: '
    basic_attack = gets.chomp.downcase
    check_attacks(poke, basic_attack)
    obtain_spec_attack(poke)
  rescue AttackNotFoundError
    retry # runs the 'begin' block again
  end
end

def obtain_spec_attack(poke)
  print 'Enter special attack: '
  spec_attack = gets.chomp.downcase
  check_attacks(poke, spec_attack)
end

def check_attacks(pokemon, attack)
  if POKEMON_ATTACKS[pokemon][attack] == nil
    puts "#{attack} is not one of #{pokemon}'s attacks, try again.."
    raise AttackNotFoundError
  else
    attack
  end
end
为了使用自定义错误,如
AttackNotFoundError
,您需要在某个地方定义错误类:

class AttackNotFoundError < StandardError; end
类攻击NotFoundError

您可以使用任何错误,例如
raise StandardError
,但最好限制您要挽救的错误,这样您就不会意外地挽救不相关的错误

我建议你看看递归。这里有一个很好的类比:我建议您看看递归。这里有一个很好的类比:如果你看代码,有不止一个调用方法。不过,该循环可能会起作用,您也可以使用rescue。我会加上一个例子。这是一个天才的想法!!!我甚至都没想过救援条款,非常感谢!当然,顺便说一句,如果口袋妖怪攻击[POKEMON][attack]==nil
通常是不必要的,你可以删除
==nil
如果
将评估它是否真实/falsy,我无法确定这是否是滥用异常。习惯上,您可能更愿意使用
throw
/
catch
。如果您查看代码,就会发现不止一个调用方法。不过,该循环可能会起作用,您也可以使用rescue。我会加上一个例子。这是一个天才的想法!!!我甚至都没想过救援条款,非常感谢!当然,顺便说一句,如果口袋妖怪攻击[POKEMON][attack]==nil
通常是不必要的,你可以删除
==nil
如果
将评估它是否真实/falsy,我无法确定这是否是滥用异常。习惯上,您可能更愿意使用
throw
/
catch