Pergunta

Eu estou usando este código para permitir que o usuário entra em nomes, enquanto o programa armazena-los em uma matriz até que eles entram uma string vazia (que deve pressionar ENTER após cada nome):

people = []
info = 'a' # must fill variable with something, otherwise loop won't execute

while not info.empty?
    info = gets.chomp
    people += [Person.new(info)] if not info.empty?
end

Este código ficaria muito mais agradável em um do ... while loop:

people = []

do
    info = gets.chomp
    people += [Person.new(info)] if not info.empty?
while not info.empty?

Neste código que eu não tenho que informações atribuir a alguns seqüência aleatória.

Infelizmente este tipo de circuito não parece existir em Ruby. Alguém pode sugerir uma maneira melhor de fazer isso?

Foi útil?

Solução

ATENÇÃO :

O begin <code> end while <condition> é rejeitado pelo autor de Ruby Matz. Em vez disso, ele sugere o uso de Kernel#loop, por exemplo.

loop do 
  # some code here
  break if <condition>
end 

Aqui está um troca de e-mail em 23 de novembro de 2005, onde Matz afirma:

|> Don't use it please.  I'm regretting this feature, and I'd like to
|> remove it in the future if it's possible.
|
|I'm surprised.  What do you regret about it?

Because it's hard for users to tell

  begin <code> end while <cond>

works differently from

  <code> while <cond>

rosettacode wiki tem uma história semelhante:

Durante novembro de 2005, Yukihiro Matsumoto, o criador do Ruby, lamentou esta funcionalidade loop e sugeriu o uso de Kernel # loop.

Outras dicas

Eu encontrei o seguinte trecho ao ler a fonte para Tempfile#initialize na biblioteca núcleo Ruby:

begin
  tmpname = File.join(tmpdir, make_tmpname(basename, n))
  lock = tmpname + '.lock'
  n += 1
end while @@cleanlist.include?(tmpname) or
  File.exist?(lock) or File.exist?(tmpname)

À primeira vista, eu assumi o modificador while seria avaliado antes do conteúdo de começar ... fim, mas que não é o caso. Observe:

>> begin
?>   puts "do {} while ()" 
>> end while false
do {} while ()
=> nil

Como seria de esperar, o loop continuará a executar enquanto o modificador é verdade.

>> n = 3
=> 3
>> begin
?>   puts n
>>   n -= 1
>> end while n > 0
3
2
1
=> nil

Enquanto eu ficaria feliz em nunca mais ver essa expressão de novo, começar ... final é bastante poderoso. O seguinte é uma expressão comum para memoize um método one-liner sem parâmetros:

def expensive
  @expensive ||= 2 + 2
end

Aqui está uma maneira feia, mas rápido para memoize algo mais complexo:

def expensive
  @expensive ||=
    begin
      n = 99
      buf = "" 
      begin
        buf << "#{n} bottles of beer on the wall\n" 
        # ...
        n -= 1
      end while n > 0
      buf << "no more bottles of beer" 
    end
end

Originalmente escrito por Jeremy Voorhis . O conteúdo foi copiado aqui porque parece ter sido retirado do local de origem. Cópias também podem ser encontradas no web Archive e em rubi zumbido Fórum . -Bill o Lagarto

Como esta:

people = []

begin
  info = gets.chomp
  people += [Person.new(info)] if not info.empty?
end while not info.empty?

Referência: Oculto de ruby ??do {} while () loop

Como sobre isso?

people = []

until (info = gets.chomp).empty?
  people += [Person.new(info)]
end

Aqui está o texto completo do link morto de hubbardr ao meu blog.

eu encontrei o seguinte trecho ao ler a fonte para Tempfile#initialize na biblioteca núcleo Ruby:

begin
  tmpname = File.join(tmpdir, make_tmpname(basename, n))
  lock = tmpname + '.lock'
  n += 1
end while @@cleanlist.include?(tmpname) or
  File.exist?(lock) or File.exist?(tmpname)

À primeira vista, eu assumi o modificador while seria avaliado antes do conteúdo begin...end, mas isso não é o caso. Observe:

>> begin
?>   puts "do {} while ()" 
>> end while false
do {} while ()
=> nil

Como seria de esperar, o loop continuará a executar enquanto o modificador é verdade.

>> n = 3
=> 3
>> begin
?>   puts n
>>   n -= 1
>> end while n > 0
3
2
1
=> nil

Enquanto eu ficaria feliz em nunca mais ver essa expressão novamente, begin...end é bastante poderoso. O seguinte é uma expressão comum para memoize um método one-liner sem parâmetros:

def expensive
  @expensive ||= 2 + 2
end

Aqui está uma maneira feia, mas rápido para memoize algo mais complexo:

def expensive
  @expensive ||=
    begin
      n = 99
      buf = "" 
      begin
        buf << "#{n} bottles of beer on the wall\n" 
        # ...
        n -= 1
      end while n > 0
      buf << "no more bottles of beer" 
    end
end

Isso funciona corretamente agora:

begin
    # statment
end until <condition>

Mas, pode ser remover no futuro, porque a instrução begin é contra-intuitivo. Veja: http://blade.nagaokaut.ac .jp / cgi-bin / scat.rb / ruby ??/ ruby-core / 6745

Matz recomendado fazê-lo desta maneira:

loop do
    # ...
    break if <condition>
end

Pelo que pude perceber, Matz não gosta da construção

begin
    <multiple_lines_of_code>
end while <cond>

porque, é semântica é diferente

<single_line_of_code> while <cond>

em que a primeira construção executa o código antes de verificar o estado, e a segunda construção testa a condição antes de ele executa o código (se). Eu levá-la Matz prefere manter a segunda construção porque combina uma construção de linha de comandos if.

Eu nunca gostei da segunda construção mesmo para se declarações. Em todos os outros casos, o computador código é executado da esquerda para a direita (eg. || e &&) de cima para baixo. Os seres humanos ler o código da esquerda para a direita de cima para baixo.

Eu sugiro as seguintes construções em vez disso:

if <cond> then <one_line_code>      # matches case-when-then statement

while <cond> then <one_line_code>

<one_line_code> while <cond>

begin <multiple_line_code> end while <cond> # or something similar but left-to-right

Eu não sei se essas sugestões irá analisar com o resto da língua. Mas em qualquer caso I prefere mantendo esquerda para a direita de execução, bem como a consistência da linguagem.

a = 1
while true
  puts a
  a += 1
  break if a > 10
end

Aqui está outra:

people = []
1.times do
  info = gets.chomp
  unless info.empty? 
    people += [Person.new(info)]
    redo
  end
end
ppl = []
while (input=gets.chomp)
 if !input.empty?
  ppl << input
 else
 p ppl; puts "Goodbye"; break
 end
end
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top