TMatch<T>

A classe TMatch<T> em Delphi é uma implementação de padrões de correspondência (pattern matching) que fornece uma maneira flexível e legível de lidar com várias condições e casos em seu código. Abaixo estão as funcionalidades e vantagens desta classe:

  1. Múltiplas Formas de Correspondência: A classe TMatch permite que você corresponda um valor T a várias condições ou casos, tornando o código mais organizado e fácil de entender.

  2. Clareza e Legibilidade: Ao usar a classe TMatch, você pode escrever código mais claro e legível, especialmente quando há várias condições ou casos a serem tratados. Cada condição ou caso é explicitamente definido, tornando o código mais fácil de seguir.

  3. Melhoria na Manutenção: A implementação do padrão de correspondência com TMatch torna seu código mais robusto e fácil de manter. Adicionar novos casos ou condições é simples e não afeta os casos existentes.

  4. Guard Clauses com CaseIf: O método CaseIf pode ser usado como uma cláusula de guarda (guard clause) para garantir que um bloco de código seja executado apenas se uma determinada condição for atendida. Isso melhora a eficiência do código, evitando a execução de código desnecessário.

  5. Comparação de Igualdade com CaseEq: O método CaseEq permite que você compare o valor T com um valor específico para executar um bloco de código se eles forem iguais.

  6. Comparação de Maior que e Menor que com CaseGt e CaseLt: Os métodos CaseGt e CaseLt permitem que você compare o valor T com outro valor para executar um bloco de código se o valor T for maior ou menor, respectivamente.

  7. Verificação de Pertencimento com CaseIn: O método CaseIn permite que você verifique se o valor T está dentro de um intervalo especificado (uma matriz) e execute um bloco de código correspondente.

  8. Verificação de Tipo com CaseIs: Os métodos CaseIs permitem verificar se o valor T é de um tipo específico e executar um bloco de código correspondente.

  9. Verificação de Intervalo com CaseRange: O método CaseRange permite que você verifique se o valor T está dentro de um intervalo definido por dois valores e execute um bloco de código correspondente.

  10. Verificação de Padrão com CaseRegex: O método CaseRegex permite que você verifique se o valor T corresponde a um padrão de expressão regular e execute um bloco de código correspondente.

  11. Manipulação de Exceções com TryExcept: O método TryExcept permite que você execute um bloco de código e capture exceções, retornando informações detalhadas sobre o sucesso ou falha da execução.

  12. Combinação de Correspondências com Combine: O método Combine permite combinar várias instâncias de TMatch<T> em uma única instância, simplificando a lógica de correspondência.

  13. Retorno de Resultado com Execute: O método Execute retorna um TResultPair que indica se a correspondência foi bem-sucedida (true/false) e, se não, fornece uma mensagem explicativa.

Em resumo, a classe TMatch<T> em Delphi é uma ferramenta poderosa para aplicar padrões de correspondência em seu código, tornando-o mais claro, legível e fácil de manter, especialmente quando você precisa lidar com várias condições e casos diferentes. É uma adição valiosa à linguagem Delphi para melhorar a estrutura e a organização de seu código.

Exemplo de uso 1 (com TTuple<K>)

var
  LDados: TTuple<string>;
  LChave: string;
  LValor: string;
  LResult: TResultPair<boolean, string>;
begin
  LDados := TTuple<string>.New(['Nome', 'Idade', 'Cidade'], ['Alice', '25', 'Nova York']);

  // Teste com a chave 'Idade'
  LChave := 'Idade';
  LResult := TMatch<string>.Value(LChave)
    .CaseEq('Nome', procedure(Key: string) begin LValor := LDados.Get<string>(Key); end)
    .CaseEq('Idade', procedure(Key: string) begin LValor := LDados.Get<string>(Key); end)
    .CaseEq('Cidade', procedure(Key: string) begin LValor := LDados.Get<string>(Key); end)
    .Default(procedure begin LValor := 'Chave não encontrada'; end)
    .Execute;
  try
    Assert.AreEqual('25', LValor);
    Assert.IsTrue(LResult.isSuccess);
    Assert.IsFalse(LResult.isFailure);
  finally
    LResult.Dispose;
  end;

Exemplo de uso 2

var
  LMatchResult: TResultPair<boolean, string>;
  LIsMatch: boolean;
  LValue: TArray<integer>;
begin
  LIsMatch := false;
  LValue := [1, 4, 8];

  LMatchResult := TMatch<TArray<integer>>.Value(LValue)
    .CaseIf(1 in [2, 8, 1]) // Guard
    .CaseIf(Length(LValue) > 2) // Guard
    .CaseEq([1, 2, 3], procedure begin LIsMatch := false; end)
    .CaseEq([1, 4, 8], procedure begin LIsMatch := true; end)
    .CaseEq([1, 9, 6], procedure begin LIsMatch := false; end)
    .CaseRegex('email@gmail.com', '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$')
    .Default(procedure begin LIsMatch := false; end)
    .Execute;
  try
    Assert.IsTrue(LIsMatch, 'Expected match to be successful');
    Assert.IsTrue(LMatchResult.isSuccess, 'Expected match to be successful')
  finally
    LMatchResult.Dispose;
  end;

Exemplo de uso 3

var
  LMatchResult: TResultPair<boolean, string>;
  LIsMatch: boolean;
  LValue: TArray<String>;
begin
  LIsMatch := false;
  LValue := ['Eu', 'Você', 'Nós'];

  LMatchResult := TMatch<TArray<String>>.Value(LValue)
    .CaseEq(['Você', 'Eu', 'Nós'], procedure begin LIsMatch := false; end)
    .CaseEq(['Eu', 'Você', 'Nós'], procedure begin LIsMatch := true; end)
    .CaseEq(['Nós', 'Eu', 'Você'], procedure begin LIsMatch := false; end)
    .Execute;
  try
    Assert.IsTrue(LIsMatch, 'Expected match to be successful');
  finally
    LMatchResult.Dispose;
  end;

Exemplo de uso 4

var
  LResult: TResultPair<string, string>;
  LEnumValue: TEnumType;
begin
  LEnumValue := TEnumType.Two;
  try
    LResult := TMatch<TEnumType>.Value(LEnumValue)
      .CaseEq(TEnumType.One, function: TValue
                             begin
                               Result := 'EnumValue is One';
                             end)
      .CaseEq(TEnumType.Two, function: TValue
                             begin
                               Result := 'EnumValue is Two';
                             end)
      .CaseEq(TEnumType.Three, function: TValue
                               begin
                                 Result := 'EnumValue is Three';
                               end)
      .Default(function: TValue
               begin
                 Result := 'EnumValue is not recognized';
               end)
      .Execute<string>
      .Ok(procedure(Valeu: string)
          begin
            // Success (LResult.ValueSuccess)
          end)
      .Fail(procedure(Value: string)
            begin
              // Failure (LResult.ValueFailure)
            end);

    Assert.AreEqual('EnumValue is Two', LResult.ValueSuccess);
  finally
    LResult.Dispose;
  end;
end;

Last updated