Diferença entre "e" e && em Ruby?

321

Qual é a diferença entre the &&e andoperadores no Ruby?

Jakub Arnold
fonte
2
Veja também Diferença entre ore|| .
Andrew Marshall

Respostas:

349

andé o mesmo que &&mas com menor precedência . Ambos usam avaliação de curto-circuito .

AVISO: andainda tem precedência mais baixa do que =você normalmente deseja evitar and. Um exemplo de quando anddeve ser usado pode ser encontrado no Guia do Rails, em " Evitando erros de renderização dupla ".

Dominic Rodger
fonte
50
Seria uma boa idéia especificar que normalmente se deve usar &&, enquanto anddeve ser usado apenas para casos muito específicos.
Marc-André Lafortune
10
Outra boa explicação aqui: devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby .
Andrew Marshall
17
No link de Andrew Marshall: "Outra maneira de pensar andé como um ifmodificador de declaração invertida : next if widget = widgets.poptorna - se widget = widgets.pop and next. Essa é uma ótima maneira de colocar isso, realmente fez com que" clique "na minha cabeça. (E oré como um unlessmodificador invertido .)
GMA
1
Combine esta resposta com os detalhes da resposta de tadman e você terá uma visão geral.
sargas
5
Avdi atualizou sua opinião sobre quando usar e vs. Basicamente, use 'e' e 'ou' para o fluxo de controle devido à sua menor precedência. devblog.avdi.org/2014/08/26/…
EricC
238

A diferença prática é a força de ligação, que pode levar a um comportamento peculiar se você não estiver preparado para isso:

foo = :foo
bar = nil

a = foo and bar
# => nil
a
# => :foo

a = foo && bar
# => nil
a
# => nil

a = (foo and bar)
# => nil
a
# => nil

(a = foo) && bar
# => nil
a
# => :foo

A mesma coisa funciona para ||e or.

tadman
fonte
2
a = foo and bar e (a = foo ) && bar prova que andtem precedência menor que &&.
Sargas
não entendi: o que "foo and bar" deve retornar?
precisa saber é o seguinte
a = foo and baré equivalente a (a = :foo) and nil. Como a atribuição retorna um valor logicamente verdadeiro ( :foo), a segunda parte avalia, o que falha, retornando nil.
Tadman
61

O Ruby Style Guide diz que é melhor do que eu poderia:

Use && / || para expressões booleanas e / ou para controle de fluxo. (Regra básica: se você precisar usar parênteses externos, estará usando os operadores errados.)

# boolean expression
if some_condition && some_other_condition
  do_something
end

# control flow
document.saved? or document.save!
Andrew Grimm
fonte
53
Na verdade, o guia agora diz para evitar and/ orcompletamente, e eles podem ter razão . Muitas vezes, a sua utilização no controlo de fluxo pode ser mais obviamente escrito com if/ unlessoperadores de qualquer forma (por exemplo, document.save! unless document.saved?)
Yarin
@akostadinov, caso você não estivesse andando de um lado para o outro: o guia Ruby Style não foi escrito pelos criadores do Ruby. Ruby foi criado por Yukihiro Matsumoto e outros, enquanto o Ruby Style Guide foi principalmente por Bozhidar Batsov.
Andrew Grimm
2
@AndrewGrimm, obrigado, bom saber. Desculpe por trollar, mas estou sinceramente confuso com alguns aspectos da realidade do rubi. Uma coisa é certa - todo projeto ruby ​​precisa de políticas rígidas de estilo para manter a base de código sustentável.
akostadinov 04/07/2014
37

||e &&vincule com a precedência que você espera dos operadores booleanos nas linguagens de programação ( &&é muito forte, ||é um pouco menos forte).

and e or têm menor precedência.

Por exemplo, ao contrário ||, ortem precedência mais baixa que =:

> a = false || true
 => true 
> a
 => true 
> a = false or true
 => true 
> a
 => false

Da mesma forma, ao contrário &&, andtambém tem precedência menor do que =:

> a = true && false
 => false 
> a
 => false 
> a = true and false
 => false 
> a
 => true 

Além do mais, ao contrário &&e ||, ande orse ligam com a mesma precedência:

> !puts(1) || !puts(2) && !puts(3)
1
 => true
> !puts(1) or !puts(2) and !puts(3)
1
3
 => true 
> !puts(1) or (!puts(2) and !puts(3))
1
 => true

A ligação fraca ande orpode ser útil para fins de controle de fluxo: consulte http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ .

Gabe Kopley
fonte
2
"ao contrário ||, ortem precedência menor que =" ... agora faz mais sentido, obrigado!
Steph Sharp
18

andtem precedência mais baixa que &&.

Mas para um usuário despretensioso, podem ocorrer problemas se ele for usado junto com outros operadores cuja precedência esteja entre, por exemplo, o operador de atribuição:

def happy?() true; end
def know_it?() true; end

todo = happy? && know_it? ? "Clap your hands" : "Do Nothing"

todo
# => "Clap your hands"

todo = happy? and know_it? ? "Clap your hands" : "Do Nothing"

todo
# => true
Santhosh
fonte
1
Obrigado, mas como a precedência de "e" é diferente de "&&"?
BKSpurgeon
2
@BKSpurgeon Veja aqui uma lista ordenada de precedência de operadores em Ruby.
thutt
5

andtem precedência mais baixa, principalmente o usamos como um modificador de controle-fluxo, como if:

next if widget = widgets.pop

torna-se

widget = widgets.pop and next

Para or:

raise "Not ready!" unless ready_to_rock?

torna-se

ready_to_rock? or raise "Not ready!"

Eu prefiro usar, ifmas não and, porque ifé mais inteligível, então simplesmente ignoro ande or.

Consulte " Usando" e "e" ou "em Ruby " para obter mais informações.

Feuda
fonte
0

Não sei se essa é a intenção do Ruby ou se é um bug, mas tente este código abaixo. Este código foi executado no Ruby versão 2.5.1 e estava em um sistema Linux.

puts 1 > -1 and 257 < 256
# => false

puts 1 > -1 && 257 < 256
# => true
Kevin Ng
fonte
1
@JakubArnold Sarcasm nunca é útil. Exemplos às vezes são.
BobRodes 14/02/19
@BobRodes Não foi um sarcasmo. Existem 7 respostas, 6 das quais já possuem exemplos.
Jakub Arnold
1
@JakubArnold Ainda achei este exemplo útil.
BobRodes 15/02/19
Estou obtendo resultados ímpares também. v1 = verdadeiro e falso p v1 # => app.rb: verdadeiro, IRB: falso v2 = verdadeiro && falso p v2 # => app.rb: falso, IRB: falso coloca 1> -1 && 257 <256 # => app.rb: false, IRB: false
Rich_F 15/04/19