(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