Функции в качестве параметров процедур

Форум для изучающих FPC и их учителей.

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

Функции в качестве параметров процедур

Сообщение Ro_jA » 03.05.2013 21:22:21

Товарищи,подскажите, это баг или фича?
Берем, скажем, процедуру с тремя параметрами. Эти параметры задаем с помощью трёх функций, работающих со строкой. Во время работы программы функции вызываются в нормальном порядке, а результаты в процедуру возвращаются в обратном. Вот пример:
Код: Выделить всё
var
        a:string;
        i:integer;

        function f1(b:string):integer;
        begin
                inc(i);
                writeln('f#',i);
                f1:=ord(b[1]);
                writeln(chr(f1));
                delete(a,1,1);
                writeln
        end;

        procedure p1(a,b,c:integer);
        begin
                writeln(chr(a));
                writeln(chr(b));
                writeln(chr(c))
        end;

begin
        i:=0;
        readln(a);
        p1(f1(a),f1(a),f1(a));
        readln
end.

Вводим строку 'abc'
На экране видим:
f#1
a

f#2
b

f#3
c
{то есть функции вызываются в правильном порядке, но потом:}

c
b
a
{то есть процедура берет их в обратном.}
Очень, знаете ли, обидная и труднообнаруживаемая проблема.
Компилятор 2.6.2.
Ro_jA
незнакомец
 
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Re: Функции в качестве параметров процедур

Сообщение Sergei I. Gorelkin » 03.05.2013 21:53:36

Фича.
Компилятор вычисляет аргументы в произвольном порядке, который может зависеть от типа вызываемой процедуры и целевой платформы.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Функции в качестве параметров процедур

Сообщение Ro_jA » 03.05.2013 22:06:21

И какая же практическая польза от этой фичи? Каким образом мне при последующем написании программ удостовериться, что все вычисляется в нужном порядке?
Ro_jA
незнакомец
 
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Re: Функции в качестве параметров процедур

Сообщение Sergei I. Gorelkin » 03.05.2013 22:38:41

Код: Выделить всё
var
  t1,t2,t3: integer;
begin
  t1:=f1(a);
  t2:=f1(a);
  t3:=f1(a);
  p1(t1,t2,t3);
end;


Код, зависящий от порядка вычисления аргументов функции, писать не нужно.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Функции в качестве параметров процедур

Сообщение runewalsh » 03.05.2013 22:39:32

Записывать во временные переменные в нужном порядке. Фича оправданна и имеет место в абсолютном большинстве компилируемых языков, т. к. предоставляет компилятору простор для оптимизации. А вот вызывать зависящие друг от друга функции в пределах одной точки следования — опасно; даже в шарподжавах, где порядок определён, это как минимум моветон.

UPD: ну вот, меня опередили. ^^
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Функции в качестве параметров процедур

Сообщение Ro_jA » 03.05.2013 22:53:28

Ну что ж, спасибо за советы. Непонятно, почему в документации ни слова на этот счет. В ref вообще ничего,а в prog я нашел строчку "If a function is called that returns a variable of type String, Set, Record, Object or
Array, then an address to store the function result in, is also passed to the procedure." которая,похоже вообще не о том.
Эмм, а как закрыть тему?
Ro_jA
незнакомец
 
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Re: Функции в качестве параметров процедур

Сообщение absdjfh » 04.05.2013 15:40:10

Ro_jA писал(а):Непонятно, почему в документации ни слова на этот счет.

Ну вот как нет, если есть? Глава 12, reference guide, expressions:
Remark: The order in which expressions of the same precedence are evaluated is not guaranteed to be left-to-right. In general, no assumptions on which expression is evaluated first should be made in such a case. The compiler will decide which expression to evaluate first based on optimization rules. Thus, in the following expression:

a := g(3) + f(2);
f(2) may be executed before g(3). This behaviour is distinctly different from Delphi or Turbo Pascal.

If one expression must be executed before the other, it is necessary to split up the statement using temporary results:

e1 := g(3);
a := e1 + f(2);
absdjfh
новенький
 
Сообщения: 60
Зарегистрирован: 21.01.2012 13:59:00

Re: Функции в качестве параметров процедур

Сообщение Ro_jA » 07.05.2013 20:32:24

Как раз хотел задать вопрос насчет порядка вычислений в этом операторе. Я не нашел этого потому, что искал в процедурах и функциях, а до выражений руки не дошли. Могли бы и там упомянуть, на самом деле. В любом случае спасибо.
Ro_jA
незнакомец
 
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Re: Функции в качестве параметров процедур

Сообщение Mirage » 09.05.2013 14:43:11

Причем тут порядок вычисления выражений?
Порядок передачи параметров зависит от calling convention. Например, можно попробовать пометить функцию p1 как pascal.
Порядок вычисления параметров, конечно, может и отличаться от порядка их передачи, но на практике это врядли.
Конечно, закладываться на определенный порядок нельзя. Т.к. он неопределенный в общем случае.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Функции в качестве параметров процедур

Сообщение absdjfh » 09.05.2013 15:47:17

Mirage писал(а):Т.к. он неопределенный в общем случае.

Он (порядок вычисления функций в выражениях и вызовах функций) неопределенный только в случае компилятора FPC. В TP (и, вероятно, delphi) можно было закладываться на такой порядок, и программа выводила (и выводит сейчас) ожидаемый (по человеческой логике) результат для любого варианта передачи параметров.
Самый правильный вариант, конечно, - не писать функций с побочными эффектами, особенно если без этого можно легко обойтись.
absdjfh
новенький
 
Сообщения: 60
Зарегистрирован: 21.01.2012 13:59:00


Вернуться в Обучение Free Pascal

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

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

Рейтинг@Mail.ru