# PHP para Iniciantes: Funções - Retorno

Continuando os artigos sobre construção de funções, chegamos a um tópico que também merece atenção e carinho: retorno. Eu falei em alguns artigos anteriores que toda função retorna alguma coisa, lembra?

**Eis que, logo em breve, isso não será mais verdade**. As coisas evoluem rápido, não é mesmo? É que recentemente lançaram nas versões candidatas de release do PHP 8.1 um tipo de retorno chamado `never`, que indica que a função nunca poderá ter retorno. Eu [fiz um teste](https://3v4l.org/Mv0HC#v8.1rc3) para validar se não era apenas um termo da boca pra fora, retornando `null` por baixo dos panos. Mas se você tentar atribuir o resultado de uma função que retorna `never`, o PHP encerrará a requisição com um **FatalError**. É sério, pode abrir o link que coloquei aí em cima para conferir.

Então esquece aquela ideia de que funções sempre retornam alguma coisa, pois agora temos essa pequena exceção.

Ainda assim, se o caso da sua função não for esse, é muito importante que você descreva na assinatura da função qual(is) tipo(s) de dados ela retorna para quem as invoca. Isso ajuda tanto ao desenvolvedor que irá consumí-la a entender por intuição o que vai acontecer, como também ajuda ao outro que fará ajustes posteriores nela a não quebrar inserindo um novo tipo de dados como retorno.

Por exemplo, suponha que nós temos uma classe chamada `Ponto`, que representa um ponto em um plano bidimensional, e outra chamada `AreaQuadrilateral`, que representa a área conectada por quatro instâncias da classe `Ponto`. Com essa área, acionaremos a função `aspirar`, que supostamente irá acionar uma rotina interna do robô aspirador para que limpe aquela região. Isso nos dá a seguinte chamada:

```php
// PHP 8

$area = new AreaQuadrilateral(
    x0y0: new Ponto(x: 0, y: 0),
    x0y1: new Ponto(x: 0, y: 230),
    x1y0: new Ponto(x: 180, y: 0),
    x1y1: new Ponto(x: 180, y: 230),
);

// bastaria informar x0, x1, y0, y1 e deixar a classe se virar, né?
// mas assim fica mais legível e compreensível pra galera, eu acho
// e ainda seriam quatro argumentos

aspirar($area);
```

Note que não há menção ao robô no código porque, teoricamente, é ele que roda esse script, beleza? Enfim...

### Você consegue dizer o que a função `aspirar` retorna?

<center><h1>. . .</h1></center>

Se você respondeu qualquer coisa, deixa eu te cortar antes que a coisa dure mais tempo: **não, não dá pra dizer**. Afinal, aqui é apenas uma chamada, não a assinatura dela. Se você tentar desenvolver advinhando as coisas sem checar o que está inserido, de fato, algo de ruim pode acontecer, rs.

> Tá, Kiko, mas você nem criou a função... Que sermão é esse, cara?

É só uma dica, não leve pro pessoal. O fato é que, se você abrir a implementação da função e o cabeçalho estiver como abaixo e a função tiver 300 `return` e 5000 linhas...

```php
function aspirar(AreaQuadrilateral $area) {
    // 5k linhas
    // 300 returns ao longo do código
}
```

Você vai xingar muito no twitter.

<center> ![Mr. Bean reagindo incrédulo](https://media.giphy.com/media/tJeGZumxDB01q/giphy.gif) </center>

Pior ainda se tiver um `mixed`, tipo de retorno inserido no PHP 8 para indicar que pode retornar qualquer coisa. É o equivalente a não colocar nada, rs. Se tiver 300 returns podendo retornar qualquer coisa, sinceramente, **meus pêsames**.

> Então qual seria o jeito "certo", Kiko?

Logo após fechar o parênteses, aquela seção dos argumentos, você pode indicar o tipo de retorno colocando o caractere de dois pontos (`:`) e informando o(s) possível(is) tipo(s) retornado(s). No caso da função `aspirar`, faz sentido retornar `bool`, concorda? `true` se conseguiu iniciar o comando de aspirar ou `false` se deu algum problema na máquina. Se todo o processo for síncrono, pode ser `true` se conseguiu aspirar toda a área ou `false` se algo deu errado no meio do caminho - como aquela sua roupa íntima largada no chão enquanto você estava recebendo visita.

**Ops**, se isso realmente aconteceu com você, não se exponha. Eu inventei, eu juro.

O ponto é: sendo um retorno booleano, a assinatura da função ficaria assim:

```php
function aspirar(AreaQuadrilateral $area): bool
{
    // ...
}
```

Note que eu coloquei a chave na linha abaixo... Porque acho muito feio escrever o retorno e abrir a chave ao lado, rs. Mas você pode colocar onde achar melhor - **DESDE QUE SEJA O PADRÃO DO PROJETO**. Sempre busquem manter um padrão impecável, por favor.

Sobre o **PHP 8**, lembra que no artigo anterior mencionei que você poderia listar várias possibilidades de tipos para um único argumento? Você também pode fazer isso na assinatura de retorno usando a mesmíssima sintaxe: `function aspirar(...): bool|int|string|QualquerCoisa`. Para engajar geral a colocar realmente todas as possibilidades e jamais deixar a seção em branco.

E em algum momento no futuro, creio eu, teremos o famoso **Generics**, que provavelmente será a **feature** favorita de todo desenvolvedor de libs e extensões em PHP. **Por quê?** Porque **Generics** é sobre dar possibilidade de criar **cenários** onde argumentos e retornos dependem de um dado inserido pelo desenvolvedor. Por exemplo, ao invés de falar que a entrada da função é `mixed` e, por isso, o retorno também é, você poderá dizer que o tipo de retorno é o mesmo do tipo inserido no argumento, criando ali, em tempo real, um **tipo genérico** que corresponderá ao tipo retornado.

Por exemplo: `function traduzir(<Midia> $midia): Midia` (essa sintaxe **ainda não existe**, tô só exemplificando mesmo). Nesse cenário, eu estou te dizendo que o resultado da tradução sairá no mesmo tipo do argumento `$midia`. Assim, eu posso traduzir um áudio, retornando outro áudio, ou traduzir um texto, retornando outro texto, etc.

E quando você estiver desenvolvendo, sua **IDE** poderá dizer qual será o retorno baseado na expressão que você inseriu no argumento, garantindo com mais precisão que você está escrevendo o código certo. Não é legal?

> Tá, Kiko, aprendi como assinar o retorno da função, mas **como faz o retorno acontecer**?

Nesse caso, usamos a **[estrutura de controle `return`](https://blog.kaiquegarcia.dev/php-para-iniciantes-estruturas-de-controle-return)**, lembra dela? Nas funções, ela serve para encerrar a interpretação da função e forçar o interpretador a voltar aonde estava antes de entrar na função com a informação que você desejou retornar.

Há muitas possibilidades do que dá pra fazer com o que uma função retorna. Por exemplo, se a função retorna um `array` e você sabe, com certeza, a quantidade de elementos que vem nele e a ordem de cada dado, você pode distribuir os elementos em variáveis em uma única linha usando a estrutura `list` ou a notação curta de construção de `array`:

```php
<?php

function retornaArray(): array
{
    return ['Kaique', 'Garcia', 'Kiko'];
}

list($nome, $sobrenome, $apelido) = retornaArray();
var_dump($nome, $sobrenome, $apelido);

// equivalente
[$nome, $sobrenome, $apelido] = retornaArray();
var_dump($nome, $sobrenome, $apelido);
```

Porém, falar sobre isso não tem muito a ver com o retorno das funções em si, é mais sobre o que você pode fazer quando aciona uma. Por isso, não vou me aprofundar muito nesses casos, beleza?

Voltando ao nosso exemplo, só haverá dois retornos possíveis: `return true` ou `return false`. Ah, claro que você pode retornar uma expressão que resulta em um booleano também, mas no final das contas, o interpretador só vai enxergar esses cenários que citei. Caso você retorne qualquer outra coisa diferente de `bool`, ou não retorne nada, o interpretador **poderá** lançar um erro.

> Como assim "**poderá**", Kiko?

Porque **PHP não é linguagem de tipagem forçada**. Se você não estiver usando a tipagem rígida (mencionada no [artigo sobre declaração de tipagens](https://blog.kaiquegarcia.dev/php-para-iniciantes-tipos-de-dados-primitivos-declarando-tipagens)), o PHP tentará converter o dado inserido para `bool`. Nesse caso, é bem provável que converta mesmo.

Mas beleza, agora você já sabe onde colocar o(s) tipo(s) e como escrever o retorno em si, mas você já sabe quais tipos pode colocar na assinatura? **Você deveria saber**, pois eu comentei no [artigo sobre declaração de tipagens](https://blog.kaiquegarcia.dev/php-para-iniciantes-tipos-de-dados-primitivos-declarando-tipagens), onde mencionei um [link para uma tabela atualizada com os tipos aceitos na documentação oficial do PHP](https://www.php.net/manual/pt_BR/language.types.declarations.php#language.types.declarations.base).

Essa tabela vale tanto para **argumentos** quanto para **retornos**. Lá também tem os tipos exclusivos para **retornos**, que são os casos do `void` e `never`. Ignore o `static`, porque isso é um retorno de **métodos**, que só vamos ver lá pra frente, beleza?

<center><h1>. . .</h1></center>

> É isso, Kiko? Acabou?

<center> ![Acabou... Pode ir...](https://media.giphy.com/media/xT0GqCd3OEQdXNdIME/giphy.gif) </center>

# Opa, peraí

Na verdade, ainda temos um tópico chato para falar. Usei a mesma tática do artigo anterior: deixei pro final porque não gosto, hahahaha. É sobre o retorno de **referências**.

Você pode retornar a referência de alguma variável ao escrever o operador de referência (`&`) antes do nome da função. Isso indica que ela irá retornar isso. Quando você acionar a função, você também precisará inserir esse símbolo (`&`) depois do operador de atribuição. Por exemplo:

```php
<?php

function &contar(): int // & antes do nome "contar"
{
    static $contador = 0;
    $contador++;
    return $contador;
}

$contador =& contar(); // & depois do operador de atribuição "="

contar();
contar();
contar();

var_dump($contador); // int(4)
```

Eu não consigo imaginar isso como real necessidade, mas deve ter alguma coisa sim por aí e que não seja loucura... Deve ter...

<center> ![Deve ter... Deve ter...](https://media.giphy.com/media/e7FNIANIPXVGYs8uJk/giphy.gif) </center>

E agora sim! Por hoje é só! Curtiu? Comenta e compartilha! Olha, eu tomei um susto danado no **BOOM** que deram lá no Twitter de ontem pra hoje. Vocês quebraram meu recorde de like e RT de uma vez só, hahaha. Fico muito animado vendo essa reação da galera e o total interesse em conhecer mais as entranhas do PHP. Dito isso, vou continuar dando o meu máximo para entreter vocês com mais informações relevantes, fechado?

E sério, alguém pode me falar o que rolou? Fiquei o tempo todo esperando alguém anunciar uma pegadinha, HAHAHAHA. Vocês são demais! Obrigado pela visita, voltem sempre!

**Inté!!**
