(Operador ternário) para procedures/functions
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
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
Curtidas 0
Respostas
Arthur Heinrich
20/12/2023
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.
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.
GOSTEI 0
Guilherme Lima
20/12/2023
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
queria só fazer isso pra procedures, pois para valores mais simples já tem o IfThen do próprio Delphi
GOSTEI 0