Forum > Russian

Почему не работает рекурсивный вызов вложенных функций без параметров?

(1/2) > >>

wanderus:
Обнаружил неприятную проблемку. Не очень понимаю, это ошибка или так задумано.
Имеется код:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.btnRecursClick(Sender: TObject);var i:integer;    a:array[0..9] of integer;   function TestRecurs:integer;  var mm: integer;  begin    if i>=9 then begin      result := -1;      Exit;    end;    Inc(i);    result := i;    Memo1.Lines.Add('TestRecurs '+IntToStr(i));    a[i] := TestRecurs;  end;   function TestRecursDummy(dummy:integer):integer;  var mm: integer;  begin    if i>=9 then begin      result := -1;      Exit;    end;    Inc(i);    result := i;    Memo1.Lines.Add('TestRecursDummy '+IntToStr(i));    a[i] := TestRecursDummy(1);  end; begin   i:=0;   ShowMessage(IntToStr(TestRecurs));   i:=0;   ShowMessage(IntToStr(TestRecursDummy(1)));end; Тут видно две идентичные вложенные функции TestRecurs и TestRecursDummy, которые отличаются только тем, что во второй функции есть фиктивный параметр.
Так вот, TestRecurs этим кодом вызывается всего 1 раз, а TestRecursDummy - 9 раз. То есть после выполнения Memo1 содержит:

TestRecurs 1
TestRecursDummy 1
TestRecursDummy 2
TestRecursDummy 3
TestRecursDummy 4
TestRecursDummy 5
TestRecursDummy 6
TestRecursDummy 7
TestRecursDummy 8
TestRecursDummy 9

Используется стандартный Lazarus 2.0.4 под Win32
В опциях проекта отключил оптимизацию - не помогает.

wanderus:
P.S. Кажется, я догадываюсь, в чем проблема.
Вот эта строчка:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---a[i] := TestRecurs; Если ее исправить на:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---a[i] := TestRecurs(); то рекурсия работает корректно.

Zoran:

--- Quote from: wanderus on December 03, 2019, 10:08:47 am ---P.S. Кажется, я догадываюсь, в чем проблема.
Вот эта строчка:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---a[i] := TestRecurs; Если ее исправить на:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---a[i] := TestRecurs(); то рекурсия работает корректно.

--- End quote ---

Ah, it is that the function implicitely creates "result variable", named the same as function name (see https://www.freepascal.org/docs-html/current/ref/refse90.html).
Therefore, when function have no parameters, there is ambiguity between this "result variable" and recursive call, which by default compiler resolves to "result variable". By adding parentheses, you tell the compiler explicitly that it is function call.

wanderus:
Thanks. I already remembered this feature.  It would be great to have warnings about such ambiguities.
It’s a good idea to always use parentheses for the future like C/C++ function calls

ASerge:

--- Quote from: wanderus on December 03, 2019, 02:01:33 pm ---It would be great to have warnings about such ambiguities.

--- End quote ---
Agree. Especially since it is NOT compatible with Delphi.
In the documentation, however, it is said: Sometimes, the call is desired, for instance in recursion in that case, the call must be forced. This can be done by adding the parenthesis to the function name.

Navigation

[0] Message Index

[#] Next page

Go to full version