Desafio PHP
Função variádica com argumentos nomeados e valor padrão
Enunciado
Crie uma função relatorio que recebe um título (string), uma lista variádica de números e um separador (string, padrão ', '). A função deve retornar uma string com o título, dois pontos, espaço e os números separados pelo separador. Os números devem ser formatados com duas casas decimais. Use argumentos nomeados para passar o separador e a lista de números.
Requisitos
- A função deve se chamar
relatorioe ter parâmetros:$titulo(string),...$numeros(variádico de float) e$separador(string, padrão', '). - Deve retornar uma string no formato
"Título: 1.00, 2.50, 3.75". - Na chamada, use argumentos nomeados para passar
separadorenumeros(como array) usando o operador de desempacotamento.... - Se nenhum número for passado, deve retornar apenas
"Título: "(título, dois pontos e espaço).
Código inicial
<?php
// Complete a função relatorio
function relatorio(string $titulo, float ...$numeros): string {
// seu código aqui
}
// Testes
echo relatorio('Vendas', 10.5, 20.75, 30.0) . PHP_EOL;
echo relatorio(titulo: 'Compras', numeros: [1.5, 2.5], separador: ' | ') . PHP_EOL;
echo relatorio('Sem números') . PHP_EOL;
Saída esperada
Vendas: 10.50, 20.75, 30.00
Compras: 1.50 | 2.50
Sem números:
Ver dica
Use array_map para formatar cada número com number_format. Para o caso vazio, implode em um array vazio retorna string vazia.
Mostrar solução
<?php
declare(strict_types=1);
function relatorio(string $titulo, float ...$numeros): string {
// Formata cada número com duas casas decimais
$formatados = array_map(fn($n) => number_format($n, 2, '.', ''), $numeros);
$lista = implode($separador ?? ', ', $formatados);
return "$titulo: $lista";
}
// Para suportar separador nomeado, precisamos ajustar a assinatura:
// Não é possível ter parâmetro variádico antes de um parâmetro normal.
// Então usamos uma abordagem alternativa: passar separador como argumento nomeado
// não funciona diretamente com variádico. Vamos modificar a função para aceitar
// um array associativo ou usar um parâmetro opcional antes do variádico.
// Solução correta: colocar $separador antes do variádico, mas aí ele não pode ser
// passado por nome se o variádico vier depois. A melhor forma é usar um array
// para os números e um parâmetro separado.
// Vamos reescrever a função para atender ao enunciado:
function relatorio(string $titulo, string $separador = ', ', float ...$numeros): string {
$formatados = array_map(fn($n) => number_format($n, 2, '.', ''), $numeros);
return "$titulo: " . implode($separador, $formatados);
}
// Agora as chamadas com argumentos nomeados funcionam:
echo relatorio('Vendas', 10.5, 20.75, 30.0) . PHP_EOL;
echo relatorio(titulo: 'Compras', separador: ' | ', numeros: [1.5, 2.5]) . PHP_EOL;
echo relatorio('Sem números') . PHP_EOL;
Passo a passo
- A função
relatoriorecebe$titulo,$separador(padrão', ') e uma lista variádica...$numeros. - Usamos
array_mapcom uma arrow function para formatar cada número comnumber_format($n, 2, '.', ''). implode($separador, $formatados)junta os números formatados usando o separador.- Retornamos a string interpolada com título, dois pontos, espaço e a lista.
- Na primeira chamada, passamos os números posicionalmente; o separador usa o padrão.
- Na segunda chamada, usamos argumentos nomeados:
titulo,separadorenumeros(com desempacotamento de array). - Na terceira chamada, nenhum número é passado, então
$numerosé um array vazio eimploderetorna string vazia, resultando em"Sem números: ".
Por que funciona
A função variádica coleta todos os argumentos extras em $numeros. Ao colocar $separador antes do variádico, podemos passá-lo por nome e ainda usar o desempacotamento para o array de números. O array_map aplica a formatação a cada elemento, e implode monta a string final. O valor padrão de $separador é usado quando não fornecido.
Erros comuns
- Colocar o parâmetro variádico antes de um parâmetro normal:
function relatorio(string $titulo, float ...$numeros, string $separador = ', ')é erro de sintaxe, pois o variádico deve ser o último. Solução: inverter a ordem, colocando$separadorantes de...$numeros. - Tentar passar
separadorcomo argumento nomeado quando ele vem depois do variádico: não é possível, pois o variádico captura todos os argumentos restantes. Solução: reordenar os parâmetros. - Esquecer o
declare(strict_types=1): pode causar conversões indesejadas. Solução: incluir no topo.
Outra forma de resolver
Usar um array em vez de variádico:
function relatorio(string $titulo, array $numeros, string $separador = ', '): string {
$formatados = array_map(fn($n) => number_format($n, 2, '.', ''), $numeros);
return "$titulo: " . implode($separador, $formatados);
}
echo relatorio('Vendas', [10.5, 20.75, 30.0]);
Prefira variádico quando a lista é naturalmente uma lista de argumentos; use array quando a lista já é um array.
Saída esperada
Vendas: 10.50, 20.75, 30.00
Compras: 1.50 | 2.50
Sem números: