PHP para Iniciantes: Expressões

Até aqui já falamos sobre muita coisa, não é mesmo? Já falamos sobre sintaxe básica, tipos de dados primitivos, variáveis e constantes. Parece pouco, mas pra quem tá começando já é uma quantidade considerável de assuntos. O legal de acompanhar esse blog é que você pode, a qualquer momento, revisar qualquer um desses assuntos se por ventura esquecer alguma coisa daqui pra frente. Digo isso porque conforme formos nos aprofundando nas próximas temáticas, iremos lidar com assuntos que usam constantemente tudo o que foi mencionado acima.

E um bom exemplo disso é o assunto de hoje, expressões, que pode envolver tudo. Inclusive, você deve ter me visto escrever algumas expressões nos exemplos anteriores...

Mas vamos definir agora: o que é uma expressão? Se você procurar no dicionário, encontrará muitos significados para essa palavra. A questão é que assuntos de computação são muito mais ligados à matemática do que linguagens naturais em si. Então, de todos os significados no dicionário, o mais próximo é o de contexto matemático:

Conjunto de letras e de números ligados uns aos outros por sinais de operações algébricas e que indica as operações que convirá efetuar sobre as medidas de grandeza dadas ou desconhecidas para lhes deduzir a medida de uma grandeza dependente delas (ex.: expressão algébrica; expressão numérica).

Exceto que, nas linguagens de programação, expressões são qualquer coisa que gere um valor, não somente operações matemáticas.

<?php

$x = $a + $b; // expressão matemática, que também é uma expressão aqui

$x = 5; // também é uma expressão matemática

$nome = 'Kaique' . ' ' . 'Garcia'; // também é uma expressão

'1' + 1; // mesmo sem o =, também é uma expressão! Afinal, aqui geramos um valor. Só não estamos usando o resultado.

1; // também é uma expressão! que resulta no inteiro 1.

__LINE__; // também (...)...

Você lembra de funções? Bem, funções também são expressões, o que chamamos de expressão dinâmica. Falamos dessa forma pois o resultado que sai dessa função pode não ser sempre o mesmo, diferente da expressão 5, que sempre resulta em 5.

No caso de funções, sempre que você aciona uma, o interpretador entra em um bloco de código específico para executar uma série de instruções e depois sair com um resultado, seja ele satisfatório ou não.

Dito isso, toda e qualquer expressão é um bloco de código, uma série de instruções. E eu posso provar, rs.

Quando você faz $x = 100 + 100 * 100 % 40, quais são as instruções que o interpretador recebe? É apenas uma expressão, com os seguintes passos:

  1. 100 * 100 = 10000;
  2. 10000 % 40 = 0 (pra quem não sabe, % é o símbolo que representa mod, uma operação matemática que serve para obter o resto da divisão de N1 por N2. Nesse caso, N1=10000 e N2=40. O resto da divisão é 0!);
  3. 100 + 0 = 100;
  4. Por fim, você ordena o interpretador a armazenar o resultado 100 em $x!

Logo, essa expressão é um bloco de código de 4 passos, equivalente à:

<?php

function aquelaExpressao(): int
{
    $x = 100 * 100;
    $x = $x % 40;
    return 100 + $x;
}

$x = aquelaExpressao();

Você também pode reescrever tudo em forma de grupo de operações, mas só faz sentido em expressões matemáticas: $x = (((100 * 100) % 40) + 100);.

Enfim, o legal de programação é justamente isso: tem uma infinidade de formas de escrever a mesma coisa de maneiras completamente diferentes.

Por exemplo: se você precisasse escrever duas expressões somando 10 + $a, mas entre a primeira e a segunda expressão você desejasse somar 1 com $a, como faria? Bom, uma das maneiras é simplesmente escrever três expressões:

<?php
// valor inicial
$a = 5;

$b = 10 + $a;
$a = $a + 1;
$b = 10 + $a;

Faz sentido? Então deixe-me mostrá-lo mais uma coisa interessante...

Incremento e decremento

Eu já mostrei isso em artigos anteriores, é simplesmente substituir a expressão $a = $a + 1 por $a++ ou ++$a, o que vai resultar na mesma expressão... Mas você sabe a diferença entre o ++ vir antes ou depois?

Pois bem, se o ++ vem antes, é chamado de pré-incremento. Se vem depois, pós-incremento. E a ideia aqui é:

  • pré: usamos o valor depois do incremento na expressão atual;
  • pós: usamos o valor atual da variável e somente depois da expressão é que incrementamos seu valor.

Dito isso, se você quiser reduzir aquelas três expressões em duas, você pode fazer:

Pré-incremento

<?php
$a = 5;

$b = 10 + $a;
$b = 10 + ++$a; // primeiro faz $a = $a + 1, depois faz 10 + $a

Pós-incremento

<?php
$a = 5;

$b = 10 + $a++; // primeiro faz 10 + $a, atribui a $b e depois faz $a = $a + 1
$b = 10 + $a;

Da mesma forma que temos os incrementos, temos os decrementos, que seguem a mesma lógica, só trocando o + por -, representando uma subtração por 1.

Se pudéssemos escrever isso em forma de classe, seria algo mais ou menos assim:

<?php // Numero.php

class Numero {
    public function __construct(
        private int|float $numero
    ) { }

    private function incrementar(): void
    {
        $this->numero = $this->numero + 1;
    }

    private function decrementar(): void
    {
        $this->numero = $this->numero - 1;
    }

    public function valor(): int|float
    {
        return $this->numero;
    }

    public function valorComPreIncremento(): int|float
    {
        $this->incrementar();
        return $this->valor(); // valor depois de incrementar
    }

    public function valorComPosIncremento(): int|float
    {
        $valorAntesDeIncrementar = $this->valor();
        $this->incrementar();
        return $valorAntesDeIncrementar;
    }

    public function valorComPreDecremento(): int|float
    {
        $this->decrementar();
        return $this->valor(); // valor depois de decrementar
    }

    public function valorComPosDecremento(): int|float
    {
        $valorAntesDeDecrementar = $this->valor();
        $this->decrementar();
        return $valorAntesDeDecrementar;
    }
}

E as execuções dessa classe seria:

<?php // index.php
require_once __DIR__ . '/Numero.php';

$numero = new Numero(5);

var_dump($numero->valor()); // retorna o valor inalterado, 5

var_dump($numero->valorComPosIncremento()); // retorna o valor 5, mas aumenta ele internamente

var_dump($numero->valor()); // retorna 6! resultado do incremento de antes

var_dump($numero->valorComPreIncremento()); // retorna 7! pois o incremento acontece antes de retornar

var_dump($numero->valor()); // retorna o valor inalterado, 7

var_dump($numero->valorComPosDecremento()); // retorna 7, mas depois diminui o valor internamente

var_dump($numero->valor()); // retorna 6! resultado do decremento de antes

var_dump($numero->valorComPreDecremento()); // retorna 5! pois o decremento acontece antes de retornar

Faz umas brincadeiras aí e me diz se ficou claro? Acho que foi o melhor exemplo que já dei sobre isso, rs.

Comparadores

Outra forma de expressão são os comparadores, que sempre resultam em um booleano. A ideia é que expressões de comparadores sempre indiquem algo que pode ser verdadeiro ou falso (respectivamente, true ou false). Dito isso, é preciso entender quais comparações são possíves de se fazer nessa linguagem, concorda? Temos uma listinha bem humilde:

  • "igual a", ==, que verifica se o valor é igual ao outro, sem contar com a diferença de tipagem;
  • "estritamente igual a", ===, que verifica se o valor e a tipagem são iguais;
  • "diferente de", !=, que verifica se o valor é diferente do outro, sem contar com a diferença de tipagem;
  • "estritamente diferente de", !==, que verifica se o valor ou a tipagem são diferentes;
  • "maior que", >, que dispensa explicações (creio eu, comenta aí se precisar que eu edito!);
  • "maior ou igual a", >=, (...);
  • "menor que", <, (...);
  • "menor ou igual a", <=.

Você pode encontrar com frequência esses comparadores juntos de blocos de condição (o famoso if).

<?php

$a = 10; // int
$b = 20; // int
$c = 10.0; // float

var_dump($a == $c); // bool(true)
var_dump($a === $c); // bool(false), pois int != float
var_dump($a != $c); // bool(false)
var_dump($a !== $c); // bool(true), pois int realmente é diferente de float
var_dump($a > $b); // bool(false), pois $b é maior que $a
var_dump($a >= $b); // bool(false)
var_dump($a < $b); // bool(true)
var_dump($a <= $b); // bool(true), pois se já é menor, o igual não muda nada

Expressões mescladas com atribuições

Dito tudo isso que falamos, ainda temos mais uma coisa legal. Escrevi propositalmente nos exemplos de incremento a sintaxe $a = $a + 1. Esse tipo de operação que usa o valor anterior da variável a ser alterada para fazer algo com outro dado pode ser resumida em uma expressão com auto-atribuição, que, nesse caso, seria $a += 1.

Expressões de auto-atribuição existem para, basicamente, todas as operações nativas entre dois valores e que são representadas por um único símbolo.

  • Soma: $variavel += $valor;
  • Subtração: $variavel -= $valor;
  • Multiplicação: $variavel *= $valor;
  • Divisão: $variavel /= $valor;
  • Mod (resto da divisão): $variavel %= $valor;
  • Concatenação: $variavel .= $texto;
  • Etc.

Sim, tem muito mais, mas envolve operações bit a bit, assuntos mais complexos. Teremos um tópico só sobre operadores, então pode ficar tranquilo!

Operador ternário

Esse aqui é bem útil, ainda falando sobre operadores. Esse aqui foi criado para simplificar atribuições condicionais.

Como assim, Kiko?

<?php

if ($algumaCoisa) {
    $valor = 1;
} else {
    $valor = 2;
}

Essa condicional pode ser reescrita em uma linha mais simples:

<?php

$valor = $algumaCoisa ? 1 : 2;

Afinal, trata-se de uma simples atribuição na variável $valor baseado no valor booleano da variável $algumaCoisa. É tipo $algumaCoisa?, se sim, então 1, se não, então 2.

Expressões declarativas

Se uma expressão é o que carrega valor, o que raios é uma expressão declarativa, Kiko?

Uma expressão cujo resultado é utilizado em outra expressão de atribuição. Por exemplo, se por algum motivo você quer inicializar duas variáveis com o mesmo valor, você naturalmente pode pensar em fazer algo similar a isso:

<?php

$a = 0;
$b = 0;

Mas você está no PHP e isso poderia estar ainda mais simples!

<?php

$a = $b = 0;

O interpretador lê $b = 0, então, executa essa expressão. Depois lê $a = $b, onde $b é zero, logo $a = 0. Fazendo com que a expressão anterior declare o valor da expressão atual. Parece bacana? Lembra até $$variáveis variáveis, não é?

E é basicamente infinito.

<?php

$contadorA = $contadorB = $contadorC = $contadorD = $contadorE = $contadorF = 0;

Que é o mesmo que:

<?php

$contadorF = 0;
$contadorE = $contadorF;
$contadorD = $contadorE;
$contadorC = $contadorD;
$contadorB = $contadorC;
$contadorA = $contadorB;

E por hoje é só! Se você gostou de falar sobre operadores, iremos nos aprofundar nisso no próximo artigo! E vamos de cabeça, hein?

Curtiu? Comenta e compartilha! Essa deu um certo trabalho de escrever pois minhas filhas me interromperam várias vezes. Porém finalmente dormiram e aqui estou completando mais um artigo pra vocês! :hehe: Espero vê-los no próximo!

Inté!