3v4l.org

run code in 500+ PHP versions simultaneously
<?php declare(strict_types=1); /** * ========================================================================== * SISTEMA BANCÁRIO FUNCIONAL EM PHP MODERN (COMPLETO) * ========================================================================== * * Conceitos aplicados do Mapa Mental: * 1. Pure Functions * 2. Higher-Order Functions (array_reduce) * 3. Immutability & Value Objects (Readonly DTOs) * 4. Function Composition * 5. Currying * 6. Lazy Evaluation with Generators (yield) * 7. Pattern Matching (match) */ /** * -------------------------------------------------------------------------- * 1. IMUTABILIDADE & VALUE OBJECTS (Readonly DTOs) * -------------------------------------------------------------------------- */ readonly class Conta { public function __construct( public string $id, public float $saldo ) {} } readonly class Transacao { public function __construct( public string $idempotencyKey, public string $tipo, // 'DEPOSITO' ou 'SAQUE' public float $valor, public string $contaId ) {} } /** * DTO Tipado para o Estado do Processamento. * Substitui o array genérico por uma estrutura 100% type-safe. */ readonly class ResultadoProcessamento { /** * @param array<string, Conta> $contas * @param array<string> $chavesProcessadas */ public function __construct( public array $contas, public array $chavesProcessadas ) {} /** * Método auxiliar puramente funcional: * Retorna uma NOVA instância de ResultadoProcessamento com os novos dados. */ public function comTransacao(Conta $novaConta, string $novaChave): self { return new self( contas: array_merge($this->contas, [$novaConta->id => $novaConta]), chavesProcessadas: array_merge($this->chavesProcessadas, [$novaChave]) ); } public function possuiChave(string $chave): bool { return in_array($chave, $this->chavesProcessadas, true); } } /** * -------------------------------------------------------------------------- * 2. PURE FUNCTIONS (Funções Puras) * -------------------------------------------------------------------------- */ function depositar(Conta $conta, float $valor): Conta { return new Conta($conta->id, $conta->saldo + $valor); } function sacar(Conta $conta, float $valor): Conta { if ($valor > $conta->saldo) { throw new InvalidArgumentException("Saldo insuficiente na conta {$conta->id}!"); } return new Conta($conta->id, $conta->saldo - $valor); } /** * -------------------------------------------------------------------------- * 3. PATTERN MATCHING (PHP 8 `match`) * -------------------------------------------------------------------------- */ function aplicarTransacao(Conta $conta, Transacao $tx): Conta { return match ($tx->tipo) { 'DEPOSITO' => depositar($conta, $tx->valor), 'SAQUE' => sacar($conta, $tx->valor), default => throw new InvalidArgumentException("Tipo de transação desconhecido: {$tx->tipo}") }; } /** * -------------------------------------------------------------------------- * 4. CURRYING * -------------------------------------------------------------------------- */ function criarValidadorValorMinimo(float $valorMinimo): callable { return fn(float $valor) => fn(callable $operacao) => $valor < $valorMinimo ? throw new InvalidArgumentException("Valor mínimo deve ser R$ {$valorMinimo}") : $operacao(); } /** * -------------------------------------------------------------------------- * 5. HIGHER-ORDER FUNCTIONS & IDEMPOTÊNCIA (`array_reduce`) * -------------------------------------------------------------------------- */ function processarComIdempotencia(array $contasIniciais, iterable $transacoes): ResultadoProcessamento { $listaTransacoes = is_array($transacoes) ? $transacoes : iterator_to_array($transacoes); $estadoInicial = new ResultadoProcessamento( contas: $contasIniciais, chavesProcessadas: [] ); return array_reduce( $listaTransacoes, function (ResultadoProcessamento $estado, Transacao $tx): ResultadoProcessamento { // Checagem de Idempotência if ($estado->possuiChave($tx->idempotencyKey)) { echo "⚠️ [IDEMPOTÊNCIA] Transação {$tx->idempotencyKey} ignorada (já processada).\n"; return $estado; } $contaAtual = $estado->contas[$tx->contaId] ?? new Conta($tx->contaId, 0.0); $novaConta = aplicarTransacao($contaAtual, $tx); echo "✅ Transação {$tx->tipo} de R$ {$tx->valor} na conta {$tx->contaId} concluída. Saldo atual: R$ {$novaConta->saldo}\n"; // Retorna um NOVO DTO imutável return $estado->comTransacao($novaConta, $tx->idempotencyKey); }, $estadoInicial ); } /** * -------------------------------------------------------------------------- * 6. LAZY EVALUATION WITH GENERATORS (`yield`) * -------------------------------------------------------------------------- */ function gerarStreamTransacoes(): Generator { yield new Transacao('tx_key_001', 'DEPOSITO', 500.0, 'conta_A'); yield new Transacao('tx_key_002', 'SAQUE', 150.0, 'conta_A'); yield new Transacao('tx_key_001', 'DEPOSITO', 500.0, 'conta_A'); // Duplicada (Ignorada) yield new Transacao('tx_key_003', 'DEPOSITO', 1000.0, 'conta_B'); yield new Transacao('tx_key_002', 'SAQUE', 150.0, 'conta_A'); // Duplicada (Ignorada) } // ========================================================================== // EXECUÇÃO DO SCRIPT // ========================================================================== echo "=== INICIANDO SISTEMA BANCÁRIO FUNCIONAL ===\n\n"; // Estado inicial $contas = [ 'conta_A' => new Conta('conta_A', 0.0), 'conta_B' => new Conta('conta_B', 100.0), ]; // 1. Teste de Currying + Validation $validarMinimo10 = criarValidadorValorMinimo(10.0); try { echo "--- Teste de Validação (Currying) ---\n"; $depositoValidado = $validarMinimo10(50.0)( fn() => depositar($contas['conta_A'], 50.0) ); echo "Depósito de R$ 50 validado! Novo saldo simulado da conta_A: R$ {$depositoValidado->saldo}\n\n"; } catch (Exception $e) { echo "Erro: " . $e->getMessage() . "\n\n"; } // 2. Processamento funcional echo "--- Processando Stream com DTO Tipado (ResultadoProcessamento) ---\n"; $resultadoFinal = processarComIdempotencia($contas, gerarStreamTransacoes()); // 3. Exibição segura dos dados lendo a propriedade $contas do DTO imutável echo "\n--- SALDO FINAL DAS CONTAS ---\n"; foreach ($resultadoFinal->contas as $conta) { echo "Conta: {$conta->id} | Saldo Final: R$ {$conta->saldo}\n"; } echo "\n--- HISTÓRICO DE CHAVES IDEMPOTENTES REGISTRADAS ---\n"; echo implode(", ", $resultadoFinal->chavesProcessadas) . "\n";

preferences:
47.13 ms | 841 KiB | 5 Q