Не понимаю что с видимостью

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Не понимаю что с видимостью

Сообщение vada » 24.12.2012 15:57:58

Вот пример кода:
Код: Выделить всё
program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, Unit1
  { you can add units after this };

var
  A, B: Double;
  R: Double;

  procedure Run(var aA, aB: Double; var aR: Double);
  var
    F: Text;
    fnc: TMyFunct;

    // В этой функции не видны переменные aA и aB !
    function Calc(aC: Double): Double; pascal;
    begin
      Result := (aA + aB) / aC;
    end;

  begin
    aA := aA * 2.0;
    aB := aB * 2.0;
    fnc := @Calc;   // Вот тут ругается компилятор.
    //Calculate(TMyFunct(@Calc), aR);
    Calculate(fnc, aR);

    Assign(F, 'test.lst');
    Rewrite(F);
    WriteLn(F,'A=',aA:4:1,'; B=',aB:4:1,'; R=',aR:4:1);
    Close(F);
  end;

begin
  A := 10.0;
  B := 20.0;
  R := 0.0;
  Run(A, B, R);
end.


И еще кусочек

Код: Выделить всё
unit Unit1;

{$mode objfpc}

interface

uses
  Classes, SysUtils;

type
  TMyFunct = function (C: Double): Double; pascal;

procedure Calculate(aFunc: TMyFunct; var aRes: Double);

implementation

procedure Calculate(aFunc: TMyFunct; var aRes: Double);
var
  C: Double;
begin
  C := 30.0;
  aRes := aFunc(C);
end;

end.


Получаю несколько проблем.
1) При компиляции кода получаю ошибку:
Код: Выделить всё
project1.lpr(29,12) Error: Incompatible types: got "<address of function(Double):Double is nested;Pascal>" expected "<procedure variable type of function(Double):Double;Pascal>"

ОБАНА!!!!
Это в строке fnc := @Calc;. Что тут не так? Мне не понятно.
Ну да ладно. Эту строку комментируем, строку Calculate(fnc, aR); комментируем, а строку //Calculate(TMyFunct(@Calc), aR); открываем.
2) В этом случае все компилируется, но при выполнении оказывается что в функции Calc переменные aA и aB не видны.
Подскажите что я делаю неправильно?

ЗЫ. На борту Windows XP и FPC 2.6.0

Добавлено спустя 19 часов 49 минут 6 секунд:
Почему требуется именно так?
Процедура Calculate реализует метод поиска оптимума функции.
Функция Calc вычисляет значение целевой функции в точке. Для вычисления целевой функции требуется еще куча данных (это те что оказались невидимыми aA и aB, .... их там прилично штук).
Ну вот я и разнес по разным модулям. Метод Calculate еще кой-где используется но с другой целевой функцией. Но не работает вся эта связка.
Сейчас у меня реализован "индусский говнокод". Во всех местах где требуется найти экстремум, а их что-то около 50, всунут код Calculate. Ну дебилизм же!
Помогите, люди добрые!!!
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Не понимаю что с видимостью

Сообщение Brainenjii » 25.12.2012 11:57:10

Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Не понимаю что с видимостью

Сообщение vada » 25.12.2012 13:51:38

Похоже, но там {$mode macpas} а у меня {$mode objfpc}. Там статус fixed а у меня ошибка в полный рост. :(
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Не понимаю что с видимостью

Сообщение Brainenjii » 25.12.2012 14:14:51

Там же ссылка в конце. Вот переработанный пример (не люблю функции в параметрах ^_^) FPC 2.6.0:
Код: Выделить всё
program project1;

{$mode objfpc}{$H+}{$modeswitch nestedprocvars}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, Unit1
  { you can add units after this };

var
  A, B: Double;
  R: Double;

  procedure Run(Const aA, aB: Double; var aR: Double);
  var
    F: Text;
    Procedure Calc(Const aC: Double; Var aResult: Double);
    begin
      aResult := (aA + aB) / aC;
    end;

  begin
    Calculate(@Calc, aR);

    Assign(F, 'test.lst');
    Rewrite(F);
    WriteLn(F,'A=',aA:4:1,'; B=',aB:4:1,'; R=',aR:4:1);
    Close(F);
  end;

begin
  A := 10.0;
  B := 20.0;
  R := 0.0;
  Run(A, B, R);
  WriteLn(R);
end.

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}{$modeswitch nestedprocvars}

interface

uses
  Classes, SysUtils;

type
  TMyProc = Procedure (Const C: Double; Var aResult: Double) Is Nested;
procedure Calculate(aFunc: TMyProc; var aRes: Double);

implementation

procedure Calculate(aFunc: TMyProc; var aRes: Double);
var
  C: Double;
begin
  C := 30.0;
  aFunc(C, aRes);
end;

end.
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Не понимаю что с видимостью

Сообщение Vapaamies » 25.12.2012 17:49:37

На самом деле ключевым словом в сообщении об ошибке было "is nested": нельзя передавать в процедурные переменные вложенные функции, т. к. они требуют контекста родительской функции для исполнения.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Не понимаю что с видимостью

Сообщение vada » 27.12.2012 11:46:53

Всем огромное спасибо!!!! Работает!
Почитать бы где про это. В документации не нашел. Раньше, помню, в турбо паскале были ключевые слова для дальнего и близкого вызова функций (far, near). Помогало. Теперь они игнорируются и {$F+} игнорируется.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Не понимаю что с видимостью

Сообщение Vapaamies » 27.12.2012 20:05:10

vada писал(а):Почитать бы где про это. В документации не нашел.

В документации к Turbo Pascal. :mrgreen:

vada писал(а):помню, в турбо паскале были ключевые слова для дальнего и близкого вызова функций (far, near). Помогало.

При этом вложенную процедуру нельзя было сделать far. И это не блажь программистов, а зависимость от контекста родительской процедуры. Вполне логично, что она сохранилась.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru
cron