Vamos dar continuidade aos estudos dos operadores em Ruby e, dessa vez, vamos abordar os operadores lógicos. Os operadores lógicos permitem-nos construir expressões complexas usando valores booleanos, e o retorno (resultado) é sempre um valor booleano. A linguagem Ruby possui sete desses operadores. Mas antes de começarmos a tratar sobre eles, vamos a alguns exemplos para nos recordar sobre a sua utilidade.
Um dos operadores lógicos é o and
, que significa "e" em inglês. O operador lógico and
retorna verdadeiro (true) apenas quando as duas proposições são verdadeiras. Em todos os outros casos, esse operador irá retornar falso (false). Para exemplificar o uso desse operador, considere o exemplo abaixo.
irb(main):001:0> a = true
=> true
irb(main):002:0> b = true
=> true
irb(main):003:0> c = false
=> false
irb(main):004:0> a and b
=> true
irb(main):005:0> a and c
=> false
irb(main):006:0> b and c
=> false
Observe que o operador and
retornou verdadeiro (true
) quando as duas variáveis eram verdadeiras (true
). Quando pelo menos uma das variáveis era falsa (false
), o retorno foi falso (false
).
Ruby possui sete operadores lógicos, ilustrados na Tabela 1, que representam quatro operações lógicas.
Operação lógica | Operador | Descrição |
---|---|---|
E | and |
Resulta verdadeiro quando os dois operandos forem verdadeiros, resulta falso caso contrário |
&& |
||
Ou | or |
Resulta verdadeiro quando pelo menos um dos dois operandos for verdadeiro, resulta falso caso contrário |
|| |
||
Ou exclusivo | ^ |
Resulta verdadeiro quando apenas um operando for verdadeiro. Quando os dois forem verdadeiros, retorna falso |
Negação | ! |
Inverte o valor lógico do operando |
not |
A Tabela 1 acima apresenta todos os operadores lógicos disponíveis em Ruby. Observe que alguns deles representam a mesma operação lógica, como o and
e o &&
, o ||
e o or
, o !
e o not
.
A operação lógica and
irá retornar verdadeiro apenas quando os dois operandos forem verdadeiros. Observe a tabela da verdade do operador and
na Tabela 2.
A | B | A and B |
---|---|---|
Verdadeiro | Verdadeiro | Verdadeiro |
Verdadeiro | Falso | Falso |
Falso | Verdadeiro | Falso |
Falso | Falso | Falso |
A operação lógica and
pode ser executada utilizando um dos dois operadores lógicos: and
ou &&
. Observe alguns exemplos de uso desse operador no Exemplo de código 1.
puts "true and true = #{true and true}"
puts "true && false = #{true && false}"
puts "false and true = #{false and true}"
puts "false && false = #{false and false}"
A operação lógica or
irá retornar verdadeiro quando pelo menos um dos operandos for verdadeiro. Observe a tabela da verdade do operador or
na Tabela 3.
A | B | A or B |
---|---|---|
Verdadeiro | Verdadeiro | Verdadeiro |
Verdadeiro | Falso | Verdadeiro |
Falso | Verdadeiro | Verdadeiro |
Falso | Falso | Falso |
A operação lógica or
pode ser executada utilizando um dos dois operadores lógicos: or
ou ||
. Observe alguns exemplos de uso desse operador no Exemplo de código 2.
puts "true or true = #{true or true}"
puts "true || false = #{true || false}"
puts "false or true = #{false or true}"
puts "false || false = #{false || false}"
A operação lógica ‘ou exclusivo’, também conhecida como xor (do inglês exclusive or), retorna verdadeiro quando apenas um dos operadores é verdadeiro. Em todos os outros casos, será retornado falso. Observe a tabela da verdade do ‘ou exclusivo’ na Tabela 4.
A | B | A ^ B |
---|---|---|
Verdadeiro | Verdadeiro | Falso |
Verdadeiro | Falso | Verdadeiro |
Falso | Verdadeiro | Verdadeiro |
Falso | Falso | Falso |
A operação lógica xor pode ser executada utilizando o operador ^
. Observe os exemplos de uso desse operador no Exemplo de código 3.
puts "true ^ true = #{true ^ true}"
puts "true ^ false = #{true ^ false}"
puts "false ^ true = #{false ^ true}"
puts "false ^ false = #{false ^ false}"
A operação lógica de negação inverte o valor lógico do operando. Se o operando for verdadeiro ele se tornará falso e se for falso se tornará verdadeiro. Observe a tabela da verdade do operador not
no quadro abaixo.
A | not A |
---|---|
Verdadeiro | Falso |
Falso | Verdadeiro |
A operação lógica not
pode ser executada utilizando um dos seguintes operadores: not
ou !
. Observe os exemplos de uso desse operador no Exemplo de código 4.
puts "not true = #{not true}"
puts "! false = #{! false}"
Crie um script em Ruby com o código apresentado nos Exemplos de código 1, 2, 3 e 4. Execute o script e veja o resultado apresentado.
Utilizando operadores lógicos e relacionais, nós somos capazes de construir expressões lógicas mais complexas. Confira os exemplos no Exemplo de código 5.
a = true
b = false
c = true
d = false
exemplo1 = (a and b) or (b and c)
exemplo2 = (d or c) and not a
exemplo3 = (a or b) or !c
exemplo4 = (3 < 4) or (a ^ c)
exemplo5 = (10 >= 10) and (a or b) or not d
puts "(a and b) or (b and c) = #{exemplo1}"
puts "(d or c) and not a = #{exemplo2}"
puts "(a or b) or !c = #{exemplo3}"
puts "(3 < 4) or (a ^ c) = #{exemplo4}"
puts "(10 >= 10) and (a or b) or not d = #{exemplo5}"
Antes de executar o Exemplo de código 5, tente determinar o resultado de cada expressão lógica (linhas de 6 a 10). Depois, execute o código e confira se você acertou.
Se você tentou determinar o resultado de cada expressão lógica da Atividade 6.2, você, provavelmente, deve ter achado algo estranho na expressão da linha 7 e talvez não saiba explicar o porquê. A expressão é a seguinte: (d or c) and not a
. Considerando que d
é false
e c
é true
, o resultado de (d or c)
é true
, e, considerando que a
é true
, not a
resulta em false
. Por fim, temos true and false
que resulta em false
. Contudo, na linha 13, o valor da variável exemplo2
, que guarda o resultado da expressão da linha 7, é true
! Como isso é possível?
Para complicar mais, se você teve a curiosidade de tentar executar a expressão da linha 7 no IRB, vai ver que o resultado da expressão é, de fato, false
. Observe o exemplo abaixo.
irb(main):001:0> a = true
=> true
irb(main):002:0> b = false
=> false
irb(main):003:0> c = true
=> true
irb(main):004:0> d = false
=> false
irb(main):005:0> (d or c) and not a
=> false
irb(main):006:0> exemplo2 = (d or c) and not a
=> false
irb(main):007:0> exemplo2
=> true
irb(main):008:0>
No exemplo anterior, definimos os valores das variáveis a
, b
, c
e d
, conforme o Exemplo de código 5 e, em seguida, executamos a expressão (d or c) and not a
, que resultou em false
. Quando atribuímos o resultado dessa mesma expressão para a variável exemplo2
, o valor dela é true
. Como é possível que o resultado da expressão seja false
, mas o valor atribuído à variável seja true
? A resposta para essa pergunta está na precedência de operadores.
Para explicar a precedência de operadores, vamos usar um exemplo da matemática. Qual é o resultado da expressão aritmética abaixo?
3 * 4 + 2 = ?
Se você respondeu que o resultado é 14, parabéns! Você acertou! E se você acertou, você levou em consideração a precedência de operadores. Mas o que é isso? A precedência de operadores determina a ordem de execução dos operadores. Ou seja, quais operações serão executadas primeiro e quais serão executadas depois. Nesse exemplo, sabemos que o operador de multiplicação tem precedência sobre o operador de soma, portanto devemos primeiro multiplicar e depois somar.
Assim como a matemática, as linguagens de programação também possuem precedência de operadores. A Tabela 6 apresenta operadores em ordem de precedência, ou seja, os operadores que aparecem no topo do quadro têm precedência (ou seja, devem ser executados primeiro) sobre os operadores que aparecem da parte de baixo no quadro subsequentes a eles.
Operador |
---|
! , ~ , + unário |
** |
- unário |
* , / , % |
+ , - |
<< , >> |
& |
| , ^ |
> , >= , < , <= |
<=> , == , === , != , =~ , !~ |
&& |
|| |
.. ,
|
? , : |
rescue |
= , += , -= , etc. |
defined? |
not |
or , and |
if , unless , while , until |
blocos { } |
Vale salientar que, assim como na matemática, o uso de parênteses garante a precedência de execução da expressão que está entre os parênteses. Um exemplo clássico é a fórmula para calcular a média aritmética entre dois números (ilustrada abaixo).
media = (a+b)/2
Os parênteses garantem que a soma a + b
será executada antes da divisão por 2, e isso é necessário porque a divisão tem precedência sobre a soma.
Para explicar porque a variável exemplo2
ficou com o valor true
quando recebeu o resultado da expressão (d or c) and not a
no Exemplo de código 5, precisamos levar em consideração a precedência de operadores. Observe, no quadro de precedência de operadores, que o operador de atribuição (=
) tem precedência sobre os operadores not
, or
e and
, portanto a atribuição é executada primeiro.
Agora vamos repensar a execução de exemplo2 = (d or c) and not a
levando em consideração a precedência de operadores. A primeira parte da expressão a ser executada é (d or c)
porque ela está entre parênteses, e o resultado será true
. Pela precedência de operadores, o próximo operador a ser executado é a atribuição (=), e é por isso que a variável exemplo2
recebe o valor true
(resultado de d or c
). O próximo operador a ser executado é o not
, portanto not a
resulta em false
. Por fim, o que resta da expressão é true and false
, que resulta em false
.
Isso explica porque o resultado da expressão (d or c) and not a
é false
, mas quando se introduz o sinal de atribuição (exemplo2 = (d or c) and not a
), a variável exemplo2
irá receber true
, que é o resultado de apenas parte da expressão (d or c
), e não dela toda.
Crie três variáveis lógicas (com valores booleanos) e combine-as utilizando os operadores lógicos. Tente prever o resultado da expressão lógica antes de executá-la no IRB.
RUBY DOC. Precedence. Disponível em: https://ruby-doc.org/core-2.4.1/doc/syntax/precedence_rdoc.html. Acesso em: 05 jul. 2017.
POINT, T. Ruby Operators. Tutorials Point. 2015. Disponivel em: http://www.tutorialspoint.com/ruby/ruby_operators.htm. Acesso em: 03 nov. 2015.
SOUZA, L. Ruby: aprenda a programar na linguagem mais divertida. São Paulo: Casa do Código, 2012. v. 1.