Конференция "Прочее" » Загадка: почему разработчики Object Pascal сделали именно так?
 
  • Тимохов Дима © (18.05.17 16:56) [0]
    Коллеги!

    1. Рассмотрим пример:

    procedure Test(const A: array of Integer);
    begin
    end;

    function Int(): Integer;
    begin
    end;

    var
      I: Integer;
    begin
      Test(1); // Ошибка компиляции
      Test(Int); // Ошибка компиляции
      Test(I); // Нет ошибки!
    end;



    2. Строка Test(I) прекрасно компилируется. Более того, в справке сказано, что это должно компилироваться.
    http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Parameters_(Delphi)#Open_Array_Parameters
    Фраза: Instead of an array, you can pass a variable of the open array parameter's base type. It will be treated as an array of length 1.

    Т.е. это не фича, а сознательно заложенное поведение.

    3. Собственно загадка. Как вы думаете, почему сделано именно так: почему можно только переменную, но нельзя результат функции? Или даже константу?!! Где логика?

    Полагаю, что могут пролить на это свет те, кто имел опыт конструирования своих языков...

    Я так и не допер(((

    ЗЫ Delphi 2007.
  • DayGaykin © (18.05.17 17:33) [1]
    У меня так собралось:


     Test(Integer(1));
     Test(Int);
     Test(I);


     Test(1); - здесь "1", видимо, не integer.
  • Dimka Maslov © (18.05.17 18:07) [2]
    Действительно непонятно. Когда я конструировал свои языки - всё было строго, если функция ожидает число - она получает число, если ожидает массив - она получает массив. А если она ожидает или массив или число, то всё равно каким образом это число или массив получены.
  • zamtmn © (18.05.17 18:33) [3]
    Тут надо ставить вопрос не почему именно так, а зачем вообще это преобразование?
  • Юрий Зотов © (18.05.17 18:35) [4]
    Константа 1 и результат функции Int адресов не имеют.
    Переменная I адрес имеет - он и передается в Test.
  • Юрий Зотов © (18.05.17 18:43) [5]
    Кроме того, просто 1 - это тип byte.
    А Integer(1) - это тип Integer.

    Можно предположить, что во втором случае заводится временная переменная, адрес которой и передается в Test - поэтому в [1] и собралось.

    Но это лишь предположение, а надо смотреть машкод.
  • Тимохов Дима © (18.05.17 20:29) [6]

    > DayGaykin ©   (18.05.17 17:33) [1]
    > У меня так собралось:
    >  Test(Integer(1));


    В D2007 не собирается. Проверял.


    > Юрий Зотов ©   (18.05.17 18:35) [4]
    > Константа 1 и результат функции Int адресов не имеют.


    Юр, не пойдёть))
    Если Integer заменить на String, то тоже не будет собираться.
    Хотя результат Int (теперь после замены это тип String) все равно передается через неявную локальную переменную. Т.е. машкод почти идентичен для [2] и [3]...
  • Юрий Зотов © (18.05.17 20:43) [7]
    >Тимохов Дима ©   (18.05.17 20:29) [6]

    Убери слово const из заголовка Test - будет собираться?
  • Тимохов Дима © (18.05.17 20:49) [8]

    > Юрий Зотов ©   (18.05.17 20:43) [7]
    > >Тимохов Дима ©   (18.05.17 20:29) [6]
    > Убери слово const из заголовка Test - будет собираться?


    Неа. Пробовал))

    ЗЫ Собстно, почему мне интересно докопаться.
    Знакомо чувство, когда тебя просят что-то доделать: добавь в ЭТО место функционал, который есть в ТОМ месте - ведь ЭТО место и ТО место суть одно и тоже почти! Это же так просто! А ты то как разраб знаешь, что это не фига не одно и то же. Т.е. хочется почувствовать себя на месте заказчика, который хочет разобраться, в чем проблемы у разрабов)) Вот почему, эти ребята из Борланда не сделали такую очевидную вещь: с переменной можно, а с функцией ни-ни!!! Интерес вряд-ли имеет практический смысл. Но интересно же!
  • Pavia © (18.05.17 21:12) [9]
    Да нету тут логики.
  • Игорь Шевченко © (18.05.17 22:35) [10]
    Тимохов Дима ©   (18.05.17 20:49) [8]


    > Вот почему, эти ребята из Борланда не сделали такую очевидную
    > вещь: с переменной можно, а с функцией ни-ни!!! Интерес
    > вряд-ли имеет практический смысл. Но интересно же!


    Посмотри генерируемый код, удовлетвори свой интерес. Всегда удивляюсь людям, которым процесс важнее результата.
  • DayGaykin © (18.05.17 23:15) [11]

    >
    > В D2007 не собирается. Проверял.
    >

    Написано object pascal, я прочёл free pascal, в нем и проверил.
  • NoUser © (18.05.17 23:23) [12]
    > 3. Собственно загадка. Как вы думаете, почему сделано именно
    > так: почему можно только переменную, но нельзя результат
    > функции? Или даже константу?!! Где логика?

    Логика начинается и тут :

    > Убери слово const из заголовка Test - будет собираться?

    - const в этом случаи имеет значение внутри, а снаружи - вызывающий и так и так передаёт адрес

    и тут:

    > Более того, в справке сказано, что это должно компилироваться. ...

    -  чтобы ускорить передачу массива если в нём только один элемент, - используя адрес на сам параметр а не на его дубль на стеке

    Test(i);
    0041D564 B8A4584200       mov eax,$004258a4
    0041D569 33D2             xor edx,edx
    0041D56B E814DAFFFF       call Test(int [4294967295],int)
    Test([i]);
    0041D570 A1A4584200       mov eax,[$004258a4]
    0041D575 8945E8           mov [ebp-$18],eax
    0041D578 8D45E8           lea eax,[ebp-$18]
    0041D57B 33D2             xor edx,edx
    0041D57D E802DAFFFF       call Test(int [4294967295],int)
    Test([i,Int,1]);
    0041D582 A1A4584200       mov eax,[$004258a4]
    0041D587 8945DC           mov [ebp-$24],eax          // -> A[0]
    0041D58A E84DDAFFFF       call Project1::Int()
    0041D58F 8945E0           mov [ebp-$20],eax          // -> A[1]
    0041D592 C745E401000000   mov [ebp-$1c],$00000001    // -> A[2]  
    0041D599 8D45DC           lea eax,[ebp-$24]          // <- @A[0]  
    0041D59C BA02000000       mov edx,$00000002          
    0041D5A1 E8DED9FFFF       call Test(int [4294967295],int)



    P.S.
    Зачем программист пишет 'Array' а потом осознанно опускает '[]'  я тоже не понял )
  • Юрий Зотов © (19.05.17 09:48) [13]
    10.1 Berlin. Компиляция с разными сигнатурами Test.

    procedure Test(const A: array of Integer);
    begin
    end;

    function Int(): Integer;
    begin
     Result := 1;
    end;

    var
     I: Integer;

    begin
     // Test(1); // Всегда ошибка
     // Test(Integer(1)); // Всегда ошибка
     // Test(Int); // Ошибка только при var
     Test(I); // Всегда без ошибок
    end.
  • Юрий Зотов © (19.05.17 09:52) [14]
    > Компиляция с разными сигнатурами Test

    Имелись в виду 3 варианта:

    procedure Test(const A: array of Integer);
    procedure Test(var A: array of Integer);
    procedure Test(A: array of Integer);
  • Дмитрий Белькевич © (19.05.17 12:28) [15]
    Так всё компилируется:


    Test([1]);
    Test([Int]);
    Test([I]);


    а это:


    Test(I)


    я бы для единообразия запретил
  • DayGaykin © (19.05.17 14:02) [16]

    > Дмитрий Белькевич ©   (19.05.17 12:28) [15]
    > Так всё компилируется:
    >
    > ?
    > 1
    > 2
    > 3
    > Test([1]);
    > Test([Int]);
    > Test([I]);
    >

    Выглядит как синтаксический мусор.
  • Дмитрий Белькевич © (19.05.17 16:03) [17]

    > Выглядит как синтаксический мусор.
    >


    Всё просто - не требуйте на вход массив, не будет мусора. А если требуете - то будьте добры его описать.
  • Тимохов Дима © (19.05.17 23:18) [18]
    Коллеги, спасибо за внимание к топику!

    Надеялся, что столпы ассемблера и опкода скажут свое веское: сделано так, т.к. только так можно генерить код и никак иначе. Собственно, интерес у меня был больше умозрительный.

    Пока в своих версиях остановился на том, что когда-то давно ребята косякнули в синтаксическом анализаторе и пропустили Text(I). А потом побоялись убирать в целях обеспечения обратной совместимости.
  • Игорь Шевченко © (20.05.17 10:32) [19]
    Тимохов Дима ©   (19.05.17 23:18) [18]

    Жаль, что так и не удалось услышать начальника транспортного цеха.
 
Конференция "Прочее" » Загадка: почему разработчики Object Pascal сделали именно так?
Есть новые Нет новых   [134431   +10][b:0][p:0.002]