(Operador ternário) para procedures/functions

20/12/2023

0

Estou praticando um pouco a programação com Delphi, e queria fazer uma espécie de "Operador ternário" para procedures/functions para não ficar usando If e Else.

A ideia era:
-> OperadorTernario(booleano, procedure, function); ou OperadorTernario(booleano, function, procedure);

tanto para: function - function, procedure - procedure, ect....

Agradeço antecipadamente por qualquer orientação ou sugestão que possam oferecer.

o código que criei por enquanto é bem limitado, pois está dividido em duas funções: uma para operações envolvendo procedures e outra para operações com funções ( as funções devem ter o mesmo tipo de retorno).. Estou em busca de orientações e sugestões para otimizar e unificar essas operações ternárias, possibilitando a execução tanto de procedimentos quanto de funções, independentemente do tipo de retorno.

Obrigado!

Código atual para testes:

https://drive.google.com/drive/folders/1GabYXu4WEgLT-sK87kHVqo9ZWtAEFj6g?usp=sharing

unit OperTernario;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TProcReference = reference to procedure;
  TProcEvent = procedure(Sender: TObject) of object;
  TMethodReference = reference to procedure(Sender: TObject);
  TFuncReference<T> = reference to function: T;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button3: TButton;
    Label1: TLabel;
    Button1: TButton;
    procedure Panel1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    function WrapEventMethod(const Method: TProcReference): TMethodReference;
    function WrapEventMethodEvent(const Method: TProcEvent): TMethodReference;
    function OperTernario(AValue: Boolean; const ATrue, AFalse: TMethodReference): Boolean; overload;
    function OperTernarioFunc<T>(AValue: Boolean; const ATrue, AFalse: TFuncReference<T>): T; overload;
    procedure procTrue;
    procedure procFalse;
    function funcTrue: Integer;
    function funcFalse: Integer;
  public
    { Public declarations }
    booleano: Boolean;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.OperTernario(AValue: Boolean; const ATrue, AFalse: TMethodReference): Boolean;
begin
  if AValue then
    ATrue(Self)
  else
    AFalse(Self);

  Result := AValue;
end;

function TForm1.OperTernarioFunc<T>(AValue: Boolean; const ATrue, AFalse: TFuncReference<T>): T;
begin
  if AValue then
    Result := ATrue()
  else
    Result := AFalse();
end;

function TForm1.WrapEventMethod(const Method: TProcReference): TMethodReference;
begin
  Result :=
    procedure(Sender: TObject)
    begin
      Method();
    end;
end;

function TForm1.WrapEventMethodEvent(const Method: TProcEvent): TMethodReference;
begin
  Result :=
    procedure(Sender: TObject)
    begin
      Method(Sender);
    end;
end;

function TForm1.funcTrue: Integer;
begin
  ShowMessage(''''''''Function True'''''''');
  Result := 0;
end;

function TForm1.funcFalse: Integer;
begin
  ShowMessage(''''''''Function False'''''''');
  Result := 0;
end;

procedure TForm1.procFalse;
begin
  ShowMessage(''''''''False'''''''');
end;

procedure TForm1.procTrue;
begin
  ShowMessage(''''''''True'''''''');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(''''''''Procedure de Objeto'''''''');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  booleano := not booleano;
  Label1.Caption := BoolToStr(booleano, True);
end;


procedure TForm1.Panel1Click(Sender: TObject);
begin
  // (procedure) -> (procedure)
  OperTernario(booleano, WrapEventMethod(procTrue), WrapEventMethod(procFalse));

  // (função) -> (função)   (Deve ter o mesmo tipo de retorno)
  OperTernarioFunc<Integer>(booleano, funcTrue, funcFalse);

  // (procedure) - (procedure de objeto)
  OperTernario(booleano, WrapEventMethod(procTrue), WrapEventMethodEvent(Button1Click));
end;

end.

Guilherme Lima

Guilherme Lima

Responder

Posts

20/12/2023

Arthur Heinrich

Esse tipo de funcionalidade é mais viável em linguagens interpretadas, onde o código é executado dinamicamente.

No caso do Delphi, o compilador precisa decidir o código em tempo de compilação e é importante que a "API", a interface da rotina seja semelhante, para que isto seja possível.

Isto elimina a possibilidade de misturar procedures e functions, ou mesmo de utilizar procedures e functions com diferenças nos parâmetros e tipos de retorno.

A orientação a objetos veio para resolver problemas semelhantes a esse, onde a classe pode ter métodos virtuais, de forma que ao instanciar a classe com um descendente da classe base, ao chamar o método, chamará a função correspondente. Mas, não é o que você pretende fazer.

No seu caso, a ideia é simplificar o código:

if <condição> then <método 1> else <método 2>;

Para:

Operador(<condição>, <método 1>, <método 2>);

Se pararmos para pensar, isso nem economiza nada. O if/then/else continua sendo necessário, mas interno à function/procedure, e seu código precisa executar mais uma chamada de procedure.

Dadas as limitações e o fato de que isto não simplifica tanto o código, eu não utilizaria esse tipo de recurso.
Responder

20/12/2023

Guilherme Lima

Entendo, no caso eu estava criando apenas para estudo mesmo, não seria para uma aplicação prática, mas valeu o esforço

queria só fazer isso pra procedures, pois para valores mais simples já tem o IfThen do próprio Delphi
Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar