Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Синтаксис
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 22.08.2017, 13:44
shonty shonty вне форума
Прохожий
 
Регистрация: 22.08.2017
Сообщения: 2
Версия Delphi: lazarus
Репутация: 10
По умолчанию Функция из переменной

Подскажите пожалуйста, как вызвать функцию из переменной?

Задача такая:
Имеется пять функций (одностроковых например: f4:=500*1.2*1000/(Rvar/100*x+R880)) и процедура (многострочная), строящая график на канве.

Можно конечно и пять процедур накопипастить, под каждую функцию... Но..

Не могу понять, как в процедуру ввести переменную (например F) и согласно условию подставлять в неё какую-либо из фцнкций (тиапа F:=f1, F:=f2, и т.д.).
Ответить с цитированием
  #2  
Старый 22.08.2017, 13:54
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Указатель на функцию. Как это делается при динамическом вызове dll.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
shonty (23.08.2017)
  #3  
Старый 23.08.2017, 06:14
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,004
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Дополню немного.
Есть 2 типа функций. Просто функции и методы класса.
Для первого варианта можно так:
Код:
type
  TFunc = function (x : double) : double;

function f1(x : double) : double;
begin
  result := x+1; // просто для примера
end;

function f2(x : double) : double;
begin
  result := x-1;
end;

function CalcFunc(x1, x2, dx : double; func : TFunc) : double;
var
  i : double;
begin
  // просто бред для примера
  result := 0;
  i := x1;
  while i <= x2 do
    begin
      result := result + func(i);
      i := i + dx;
    end;
end;

// где-то вызов
begin
  writeln('f1 ->', CalcFunc(1,5,0.2,f1);
  writeln('f2 ->', CalcFunc(1,5,0.2,f2);
end;

Для второго случая есть 2 подварианта.

а. Тоже самое, только тип описан как
Код:
type
  TFunc = function (x : double) : double of object;
тогда в основную функцию можно передавать методы любого класса.

б. Передавать объект класса. тогда их можно "нанаследовать" от одного родителя. Там есть еще вариант с мета классом.
Код:
unit Unit2;

interface

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

type
  TFuncClass = class
    class function Name : String; virtual;
    class function f(x : double) : double; virtual;
  end;

  TMetaClass = class of TFuncClass;

  TF1 = class(TFuncClass)
    class function Name : String; override;
    class function f(x : double) : double; override;
  end;

  TF2 = class(TFuncClass)
    class function Name : String; override;
    class function f(x : double) : double; override;
  end;

  TForm2 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    function Calc(x1, x2, dx : double; cls : TMetaClass) : double;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

class function TFuncClass.Name : String;
begin
  result := 'TFuncClass';
end;

class function TFuncClass.f(x : double) : double;
begin
  Raise Exception.Create('Should not be called.');
end;

class function TF1.Name : String;
begin
  result := 'f1';
end;

class function TF1.f(x : double) : double;
begin
  result := x + 1;
end;

class function TF2.Name : String;
begin
  result := 'f2';
end;

class function TF2.f(x : double) : double;
begin
  result := x - 1;
end;

function TForm2.Calc(x1, x2, dx : double; cls : TMetaClass) : double;
var
  i : double;
begin
  result := 0;
  i := x1;
  while i <= x2 do
    begin
      result := result + cls.f(i);
      i := i + dx;
    end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Add(Format('class %s, name %s -> %.4f',[TF1.ClassName,TF1.Name,Calc(1,5,0.2,TF1)]));
  Memo1.Lines.Add(Format('class %s, name %s -> %.4f',[TF2.ClassName,TF2.Name,Calc(1,5,0.2,TF2)]));
end;

end.
В результате нажатия на кнопку в Memo имеем:
Код:
class TF1, name f1 -> 78,0000
class TF2, name f2 -> 38,0000
Обрати внимание на тип TMetaClass.

ЗЫ. Я там совместил вызов собственно функции, форматирование строки и ее добавление в Memo. Думаю, разберешся.

ЗЗЫ. Для особо умных. Мне просто было интересно - помню ли я как работать с метаклассами, последний раз делал такое лет 8 назад. Что-то еще помню, написал с первого раза без ошибок.

Последний раз редактировалось lmikle, 23.08.2017 в 06:17.
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
shonty (23.08.2017)
  #4  
Старый 23.08.2017, 09:34
shonty shonty вне форума
Прохожий
 
Регистрация: 22.08.2017
Сообщения: 2
Версия Delphi: lazarus
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Дополню немного.
Совсем чуть-чуть
Цитата:
Сообщение от lmikle
...Есть 2 типа функций. Просто функции и методы класса.
Для первого варианта можно так:
Да, спасибо, выбрал первый вариант, разобрался, работает.

PS
Мне, как простому советскому радиолюбителю, для подбора резисторов в регуляторе тока (а зависимости сильно нелинейны) нужна программа для отображения графиков.
А хотел выкрутится так:
var a, b, c, d, e;
F:=a*(fnc1)+b*(fnc2)+c*(fnc3)+d*(fnc4)+e*(fnc5)
и подстановкой переменных a,b,c,d,e в "0" и "1" выбирать нужный участок выражения
Теперь сделаю как положено
Ответить с цитированием
  #5  
Старый 23.08.2017, 21:38
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,004
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Если пишешь для себя, то сойдет. Если собираешься делиться, то еще приделай возможность грузиить эти функции из dll, тогда можно будет расширять набор функций не меняя основную программу. Код не намного сложнее получится. Только надо будет сделать получение адресов таких же функций из dll'ей и сохранение их в спике для дальнейшего вызова.
Ну и , насколько я помню, там еще куча интересных зависимостей есть, фильтров от емкостей и индуктивностей, например).
Ответить с цитированием
  #6  
Старый 25.08.2017, 08:46
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Эх, эмбаркадера им лямбды с дженериками дала — используй лямбды с дженериками, используй — не хочу.
Код:
function demo(f1, f2: TFunc<integer, Integer>): integer;
begin
  result := f1(f2(1)); // compose functions
end;

...

foo := demo(
  function (a: integer): integer
  begin
    result := a+1;
  end,
  function (a: integer): integer
  begin
    result := a-1;
  end)

...
использование лямбд из переменных

f1 =   function (a: integer): integer
  begin
    result := a+1;
  end;

f2 =   function (a: integer): integer
  begin
    result := a-1;
  end;

bar = demo(f1, f2)
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию

Последний раз редактировалось M.A.D.M.A.N., 25.08.2017 в 08:49.
Ответить с цитированием
Этот пользователь сказал Спасибо M.A.D.M.A.N. за это полезное сообщение:
shonty (25.08.2017)
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 00:38.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter