IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

> Дискриминантные записи - GNAT, (разделено)
сообщение
Сообщение #1


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +



procedure Test is

type test(d: integer := 0) is record
case d is
when 0 => f1: integer;
when others => f2: integer;
end case;
end record;

t1, t2, t3: aliased test;
b: boolean;

function set(t: access test) return boolean is
begin
t.all := t1; -- raised CONSTRAINT_ERROR : test.adb:24 discriminant check failed
return true;
end;

begin
t1 := (d=>0, f1=>0);
t2 := (d=>1, f2=>1);
t3 := (d=>1, f2=>1);
t2 := t1; -- тут всё нормально отрабатывает
b := set(t3'access);
end Test;



И что делать с этим
raised CONSTRAINT_ERROR : test.adb:24 discriminant check failed
?

В процедуре через out-параметр присвоилось нормально, однако.
А вот t3'access.all := t1'access.all; - ошибка дискриминанта

Почему прямо присваивать можно, а через указатель - нельзя? Так и написано в стандарте?

Если поставить точку останова, а потом добить пустых строчек так, чтобы эта точка оказалась на строчке, на которой ничего нет, а потом отрубить отладчик, пересобрать код, перезапустить отладчик, то эту точку останова уже не убрать.

Дизассмеблер не взлетел: Couldn't get assembly code.

Кстати, смысла на ограничения параметров в функциях нет никакого. Избавление от побочных эффектов? Ха, толку, если можно писать во внешние переменные. Зато костыль с access получится на славу по уродливости.
Зачем вообще языки Паскалевого семейства делают ненужное разделение на процедуры и функции? Да, концепция красивая, типа процедура - то, что выполняется, функция - то, что возвращает значение, но в условиях реальности она только мешает.

Сообщение отредактировано: TarasBer -


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
2 страниц V  1 2 >  
 Ответить  Открыть новую тему 
Ответов(1 - 19)
сообщение
Сообщение #2


Гость






Цитата
И что делать с этим
raised CONSTRAINT_ERROR : test.adb:24 discriminant check failed
Думать, прежде, чем писать такие вещи. Ибо компилятор на 100% прав. Смотри ,что происходит: до тех пор, пока ты пользуешься копированием вида t1 := t2 - компилятор не проверяет легальность такого копирования, он просто берет и копирует все содержимое одной записи в другую. А вот когда ты делаешь ссылками - тут все становится гораздо интереснее. Компилятор сначала проверит, а имеешь ли ты право это сделать, совпадает ли дискриминант. И только когда совпадает - все пройдет без выброса исключения. Смотри:
   function set(t: access tmain) return boolean is
begin
t.all := t1;
return true;
end;

-- t1, t2, t3, t4: aliased tmain;
t1 := (d=>0, f1=>0);
t2 := (d=>1, f2=>1);
t3 := (d=>1, f2=>1);
t4 := (d=>0, f1=>12);
b := set(t4'access); -- Дискриминант совпал - все нормально... Не совпадет - будут проблемы


Цитата
Кстати, смысла на ограничения параметров в функциях нет никакого.
Правильно. Поэтому Стандарт Ada 2012 отменяет это ограничение. Как только он будет окончательно принят и будет создан компилятор, полностью поддерживающий новый Стандарт - можно будет пользоваться in out параметрами и в функциях.

Цитата
Дизассмеблер не взлетел: Couldn't get assembly code.
У меня тоже так показывает. Ровно до того момента, как программа будет запущена. Запустил - получаю код в окошке Assembly. Я надеюсь в настройках проекта Switches -> Ada Linker не стоит галка на Strip symbols? Если стоит - то не будет ни Assembly, ни отображения регистров процессора.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> Компилятор сначала проверит, а имеешь ли ты право это сделать, совпадает ли дискриминант. И только когда совпадает - все пройдет без выброса исключения.

Только я так и не понял, почему он прав и нафига он это проверяет? И что, главное, делать с этим?
Мне суппресс дискриминанта лепить?
(и значение дискриминанта по умолчанию выставить на самую длиную ветку, а то он, кажется, память по разному выделяет указателям на структуры с разным дискриминантом)

> Я надеюсь в настройках проекта Switches -> Ada Linker не стоит галка на Strip symbols?

Галочки у меня там не стоит, регистры показываются, дизассемблер - нет.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
Только я так и не понял, почему он прав и нафига он это проверяет?
Значит, тебе не нужна Ада. Используй С и действуй без проверок. А писать на одном языке в стиле другого - это значит заранее обрекать проект на провал. Проверяет - потому что работа со ссылочными типами контролируется гораздо серьезнее, чем работа с типами обычными. Кстати, я бы добавил еще и ограничение по простому присваиванию дискриминантных записей. Разные дискриминанты - до свидания, получите Constraint_Error безо всяких разговоров (если не отключался контроль).

Цитата
И что, главное, делать с этим?
Мне суппресс дискриминанта лепить?
Да, но не глобально, а локально, только в функции, где происходит копирование:
   function set(t: access tmain) return boolean is
pragma Suppress (Discriminant_Check);
begin
t.all := t1;
return true;
end set;

. Теперь при помощи этой функции любые записи могут присваиваться друг другу (предупреждаю сразу: я бы так не делал - чревато ошибками. На простых типах полей может и отработать, на сложных начнутся глюки. Я вообще стараюсь Suppress-ы не использовать). В других частях кода останется поведение по-умолчанию.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гость






Мне всего-то надо создать в куче сущность с дискриминантом, неизвестным на этапе компиляции. И чтобы значение этой сущности устанавливала функция через out access-параметр.

> Кстати, я бы добавил еще и ограничение по простому присваиванию дискриминантных записей.

Тогда они теряют смысл. Особенно, если value for discriminant must be static.

> Да, но не глобально, а локально, только в функции, где происходит копирование:

Ну я локально и сделал, но уродство получается. Я тоже не считаю, что подавление - это нормальное решение.
А контроль мне нужен, чтобы не использовать случайно сущности не по назначению (то есть не в соответствии с дискриминантом). Но мне нужна и возможность на ходу изменять назначение. Так-то я могу забить на дискриминант, написать через структуры, у которых используются 3 параметра из 10 (а чё, я привык после ВинАПИ), но это ж не круто, интересно всё-таки изучить этот момент и что из него можно выжать легально (без затыкания рта контролёру).
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
Тогда они теряют смысл. Особенно, если value for discriminant must be static.
Я сказал на операцию присваивания, а не на операцию инициализации:

a := (d => 0, f1 => 1);
b := (d => 1, f2 => 2);

a := b; -- Это должно вызвать Constraint_Error
b := (d => 0, f1 => 1); -- Это - нет

Еще раз возвращаемся к тому, зачем были созданы записи с вариантами вообще и дискриминантные - в частности. Затем, чтобы контролировать, имеешь ли ты в данный конкретный момент (для установленного дискриминанта) обращаться к данному конкретному полю, или нет. А теперь см. сюда:

with ada.Text_IO;

procedure Main is

type tmain(d: integer := 0) is record
case d is
when 0 =>
f1: integer;
when others =>
f2: integer := 0;
f3: integer := 0;
end case;
end record;

t1, t2, t3: aliased tmain;

begin
t1 := (d => 0, f1 => 1);
t2 := (d => 1, others => 2);
t3 := t1; -- Это - безопасное присваивание
t2 := t1; -- Это - "опасное" присваивание, разные дискриминанты
ada.Text_IO.Put_Line (integer'image(t1.f1));
ada.Text_IO.Put_Line (integer'image(t2.f2) & " " & integer'image(t2.f3));
ada.Text_IO.Put_Line (integer'image(t3.f1));
end main;

Как думаешь, что будет выведено на экран? Не запуская программу попробуй ответить...

Вот как раз тогда, когда ты работаешь через access-параметры, контроль именно такой, каким должен быть.

Цитата
Но мне нужна и возможность на ходу изменять назначение.
Меняй. По правилам языка, а не по своим правилам, и не так, как ты привык это делать в других языках. По правилам Ады, чтобы сменить назначение записи (т.е., изменить значение дискриминанта), ты должен при помощи агрегата установить новый дискриминант и ВСЕ соответствующие ему поля. Только тогда ты сможешь избежать того, что я пытался показать тебе вышеприведенной программой.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> Затем, чтобы контролировать, имеешь ли ты в данный конкретный момент (для установленного дискриминанта) обращаться к данному конкретному полю, или нет.

Правильно, мне это как раз даже нужно, мне этого реально не хватало в Дельфи.

> b := (d => 0, f1 => 1); -- Это - нет

А если я не знаю (на этапе компиляции), какое именно d мне понадобится?

case a.d is
when 0 => b := (b => 0, f1 => a.f1);
when 1 => b := (b => 1, f2 => a.f2);
when 2 => b := (b => 2, f2 => a.f2);
when 3 => b := (b => 3, f2 => a.f2);
when 4 => b := (b => 4, f2 => a.f2);
when 5 => b := (b => 5, f2 => a.f2);
when 6 => b := (b => 6, f2 => a.f2);
...
when others => raise Zachem_Tak_Mnogo_Ya_Ustal_Kopirovat;
end case;


Нет, спасибо.

> Как думаешь, что будет выведено на экран? Не запуская программу попробуй ответить...

t2.f2 и t2.f3 не должны вывестись вообще, но если заставить, то будет
Код

1
1 2
1

Во второй строке 1, а не 2, потому что его затёрло поле f1, находящееся по этому же адресу.
(я угадал? Программу не запускал)

Не вижу в этом примере ничего опасного. Программа должна срезаться при попытке вывести t2.f2 и t2.f3. А в присваивании нет ничего такого. t2.f1 будет честно равно единице.

> ты должен при помощи агрегата установить новый дискриминант и ВСЕ соответствующие ему поля.

А если я не знаю новое значение дискриминанта на этапе компиляции?

Добавлено через 3 мин.
Кстати, как сдвинуть выделенный текст вправо-влево (аналог ctrl+k+i, ctrl+k+u)?


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Цитата
А если я не знаю (на этапе компиляции), какое именно d мне понадобится?
<...>
Нет, спасибо.
Пожалуйста. Только тебе это не поможет - ты все равно получишь Constraint_Error. Выбор у тебя невелик. Либо отказаться от использования discriminant records и решить задачу по-другому, либо воспользоваться procedure вместо function (это тоже не будет работать со всеми вариантами, см. ниже), либо отключать проверку дискриминанта. Ну, и четвертый вариант: ждать выхода компилятора, полностью поддерживающего Ada 2012.

Ада тебе не позволит никакими ухищрениями обойти контроль дискриминанта в любом объекте, расположенном в куче, либо вообще в любом объекте, если ты обращаешься к нему через ссылку. Обрати внимание:
procedure Main is
type tmain(d: integer := 0) is record
case d is
when 0 =>
f1 : integer;
when others =>
f2: integer := 0;
f3: integer := 0;
end case;
end record;

procedure copy(to : in out tmain; from : tmain) is
begin
to := from;
end copy;

t1: aliased Tmain;
t2: aliased Tmain;
t3: access TMain;
begin
t1 := (d => 0, f1 => 1);
t2 := (d => 1, others => 2);
t3 := new TMain'(D => 1, others => 5);

copy(t2, t1); -- Это отработает без проблем
copy(t1, t3.all); -- Это работать не будет - ссылка, контроль будет усилен
end Main;

Контроль можно только отключить. Хочешь - отключай (если уверен, что это не приведет в дальнейшем к проблемам).

Цитата
Кстати, как сдвинуть выделенный текст вправо-влево (аналог ctrl+k+i, ctrl+k+u)?
Без понятия. Не требовалось ни разу, у меня на сохранение файла повешено его переформатирование, каждый раз когда я жму Ctrl+S, исходник приводится к тому виду, который я установил в "Pretty Printer" в настройках проекта. Потом при проверке стиля проблем гораздо меньше.

Можно сделать такое форматирование вручную, Edit -> Pretty Print.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> Либо отказаться от использования discriminant records и решить задачу по-другому,

Ну я пока так и делаю.

> либо воспользоваться procedure вместо function (это тоже не будет работать со всеми вариантами, см. ниже),

Неудобно.

> либо отключать проверку дискриминанта.

Неправильно.

> Ну, и четвертый вариант: ждать выхода компилятора, полностью поддерживающего Ada 2012.

Да уж жду с нетерпением. Кстати, а будет ли добавлена конструкция return when, по аналогии с exit when?

В общем, я так и не понял реальную причину, по которой контроль за ссылками сильнее, чем за просто записями. Я предположил, что может память для них по разному выделяется и попытка присвоить длинную ветку короткой может испортить данные в куче, хотя это вряд ли, для записей с дискриминантом по умолчанию, как написано, в стандарте, память всегда выделяется под самую длинную ветку.

> Без понятия. Не требовалось ни разу

ctrl+k+i и ctrl+k+u мне уже не нужны, ctrl+tab намного круче!

Отладчик что-то какой-то нестабильный.
На пустом месте выдал:
0x6a34f630 in system.soft_links.abort_defer_nt () from C:\Program Files\ADA\bin\libgnat-2010.dll


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
для записей с дискриминантом по умолчанию, как написано, в стандарте, память всегда выделяется под самую длинную ветку.
В Стандарте? Где именно, можно уточнить? Ибо это не выполняется ни разу. Проверь, чему равен t1'Size, а чему - t2'Size (где t1 имеет дискриминант = 0, а t2 - дискриминант = 1). А ведь использование этого поля не ограничивается обычным селектором. Я ж могу и так сделать:
   type Vector is array(Positive range <>) of Integer;
type tmain (d : Integer := 0) is record
case d is
when 0 =>
f1 : Integer;
when 1 .. 50 =>
a : Vector (1 .. d);
f2 : Integer := 0;
f3 : Integer := 0;
when others =>
f4 : Integer;
end case;
end record;

, и это тоже дискриминантная запись. Какой теперь будет размер у tmain(0)? Неужели такой же, как и у tmain(48)? У меня что-то не получилось (я под Debian-ом сейчас, попробуй под Виндой, на всякий случай. Хотя я очень сомневаюсь). Показывает при d = 0: Size = 64 бита, а при d = 48: Size = 1632 бита. Где ж наибольшая длина? И какая она, кстати? Если в ветке when others описать еще один массив, тоже зависящий от D, то максимальный размер может быть совместим с общим объемом памяти в системе. Однако при корректной работе с такими записями все будет нормально. Правда предупреждение тебе компилятор-таки даст, мол Storage_Error может приключиться, если слишком большой дискриминант будет.

Цитата
Кстати, а будет ли добавлена конструкция return when, по аналогии с exit when?
Что-то я не помню такого предложения на 2012. Хотя раньше - помню. Было в драфте того же документе, Ada 9X Project Report, под кодом Reference RR-0614: "Allow WHEN/RETURN in functions similar to EXIT/WHEN in loops."

В итоговой версии документа этого предложения уже нет, не вышло оно из драфта. Причины непонятны.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> В Стандарте? Где именно, можно уточнить? Ибо это не выполняется ни разу.

Ну не в стандарте, а в учебнике (если я правильно его понял):

Прикрепленное изображение

Компилятор интересно ругнулся на попытку написать if i in value1 | value2

сказал что-то типа "это будет доступно в 2012 году". Это так и есть?


Ещё я заметил, что можно создавать локальные шаблонные функции, инициализируя их параметрами, неизвестными на этапе компиляции. Жаль только, что с этими функциями ничего такого больше делать нельзя, а ведь лямбды и генерация кода по ходу выполнения были так близко...

Ещё я заметил, что в стандартных модулях нету моднявой записи SomeObject.SomeMethod(parameters), есть только тёплая ламповая SomeMethod(SomeObject, parameters), это потому, что решили не добавлять этого в язык?

Короче, я тут родил, пока изучал язык, небольшую программу (калькулятор с разбором выражений), если интересно:

Прикрепленный файл  test_ada.rar ( 8.07 килобайт ) Кол-во скачиваний: 466


В целом, язык оставил впечатление, как очень простой и минималистичный. Я не знаю, почему Вирту и Хоару он показался сложным, наверное, он для своего времени был слишком крут.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Цитата
это потому, что решили не добавлять этого в язык?
Оно уже сейчас есть в языке. Но только в А2005, а как должен читать код человек, только что пришедший с А95? Там ведь так нельзя было делать. В целях удобства пользователей это делается. С точки зрения компилятора эти 2 типа записи абсолютно одинаковы.

Цитата
Ну не в стандарте, а в учебнике (если я правильно его понял):
Не совсем. Тут размер еще зависит от способа описания переменной. То есть, если ты описываешь переменную так, что ее дискриминант становится постоянным и не допустимо его дальнейшее изменение (для этого достаточно написать v : TMain(0); скажем), то размер записи будет равен размеру жестко установленного варианта. Если же переменная описана с возможностью изменения дискриминанта, то размер ее будет равен размеру ее максимального варианта. с этим аккуратнее будь. И учти, что в A95 (если компилируешь без ключа -gnat05) у aliased-записи нельзя было менять дискриминант вообще, в то время как у обычной - согласно общим правилам. То есть,
   t13 : aliased TMain1 := (d => 0, f1 => 1);
-- ...
t13 := (d => 1, others => 3); -- Ада 95 вылетала с Constraint_Error

В 2005 это ограничение сняли, теперь можно менять дискриминант в данном случае.

Цитата
сказал что-то типа "это будет доступно в 2012 году". Это так и есть?
Да, в А2012 вводится set notation, можно будет записывать if a in b .. c | d | e then ...

Кроме этого должны быть разрешены Case-выражения, типа
A := (case B is when 1 => 10, when 2 => 50, when others => 0);

, есть еще много изменений...

Цитата
Я не знаю, почему Вирту и Хоару он показался сложным
Вирт был обижен, что не его поделку выбрали в качестве базы для нового языка, а проект Ишбиа. Хоар работал там же, в одной группе с Виртом, так что причина - та же, скорее всего.

P.S. Проект чуть позже посмотрю, хорошо?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> С точки зрения компилятора эти 2 типа записи абсолютно одинаковы.

Странно, у меня не вышло (стоит режим 2005, с 83 и 95 галочки сняты). Говорит, "неверный префикс". Или это потому, что я не трогал объявление функции? А как тогда объявлять надо?

> Кроме этого должны быть разрешены Case-выражения, типа

А они позволят писать что-то типа

y := (case b is when true => cos, when false => sin)(x)?

И почему нету end case? Красивее и логичнее бы смотрелось с end case и без внешних скобок, была бы унификация с имеющимся case, то есть просто было бы надаление case свойством возвращать значения.

> Вирт был обижен, что не его поделку выбрали в качестве базы для нового языка

Модула-2? А почему "поделка"?



--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Я не про Модулу в данном случае. Я про тот проект, который они предоставили на обсуждение комиссии, выбравшей четырех претендентов. Этот проект был основан на Алголе и был откровенно слабым, Вирт его упростил до предела, что потом неоднократно делал со всеми своими проектами, включая Оберон и Компонентный Паскаль (Вирт и потом говорил, что "для сложных задач должны быть простые решения", но то что у него получилось в конкурсе было слишком просто и не удовлетворяло условиям)

Цитата
А они позволят писать что-то типа
Подождем окончательной реализации. Я бы пока сказал "не планируется". С синтаксисом надо уточнить, но по моему в описании этой фичи как раз не было end case

Цитата
Странно, у меня не вышло (стоит режим 2005, с 83 и 95 галочки сняты). Говорит, "неверный префикс"
Тип должен быть теговым и объявляться в другом пакете:
Ads:
   type X is tagged record
Val : Integer;
end record;
procedure P(Obj : in out X; Value : Integer);


Adb:
   procedure P(Obj : in out X; Value : Integer) is
begin
Obj.Val := Value;
end P;


Использование:
with MyRec; use MyRec;
procedure Main is
Rec : X;
begin
Rec.P (Value => 10); -- прекрасно компилируется
end Main;

 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Гость






> Я не про Модулу в данном случае. Я про тот проект, который они предоставили на обсуждение комиссии, выбравшей четырех претендентов. Этот проект был основан на Алголе и был откровенно слабым, Вирт его упростил до предела, что потом неоднократно делал со всеми своими проектами, включая Оберон и Компонентный Паскаль (Вирт и потом говорил, что "для сложных задач должны быть простые решения", но то что у него получилось в конкурсе было слишком просто и не удовлетворяло условиям)

А как назывался-то? Я в Википедии не могу найти что-то упоминания о проекте Вирта.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Гость






Не знаю, было ли у того проекта отдельное название, ведь группа Вирта не вошла даже в финальную "цветную" четверку (Красный, Желтый, Зеленый и Синий), а вылетела раньше. Но Вирт продвигал там идеи Алгол-W, того самого, которым он в свое время предлагал заменить Алгол-60, и после НЕутверждения которого Вирт обрушился с критикой на "Комитет по стандартизации Алгола". История повторилась, его проект опять не выбрали, и опять он начал критиковать все предложения, продолжающие соревноваться между собой. По ходу, неудачник он какой-то...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Гость






> Но Вирт продвигал там идеи Алгол-W

Почитал в английской википедии. Мне понравилось, что одно слово для процедур и функций, а то зачем для слова для одинаковой сущности вводить?

> По ходу, неудачник он какой-то...

Ну не знаю, одна удача у него есть, самая главная (Паскаль), и хватит. Много удач одному человеку не положено.

> История повторилась, его проект опять не выбрали, и опять он начал критиковать все предложения, продолжающие соревноваться между собой.

Ну так делать не стоит, да, но с кем не бывает?

А в стандарте-2012 будут лямбды и всякие возможности на ходу генерировать функции?
(мои попытки локально сгенерировать шаблонную функцию на основе входных параметров и передать наружу обломались).
А то вот Дельфи в 2009 ввели, С++0х всё вводят, как бы не отстать.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Гость






Цитата
мои попытки локально сгенерировать шаблонную функцию на основе входных параметров и передать наружу обломались
Что именно ты пробовал сделать, можно посмотреть? И, заодно, как именно ты хочешь это использовать. Я к тому, что использованию шаблонной функции должна предшествовать ее инстанциация определенным типом/значением/функцией.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Ну классический пример (из http://8vmr.livejournal.com/6114.html пункт 2):



procedure New_Func(i: integer) is -- или функция, возвращающая указатель на функцию...

generic
i: integer;
function Adder(x: integer) return integer;

function Adder(x: integer) return integer is
begin
return x + i;
end;

function My_Adder is new Adder(i);
-- получили функцию с параметрами неизвестными на этапе компиляции, как передать её наружу?

begin
-- ???
end;




Может и это кажется надуманным, но все технологии поначалу такими кажутся.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Гость






Стоп. Ада такого не позволит по одной простой причине: на момент выхода из New_Func вложенная функция прекратит существование. Это отслеживается компилятором, и как только функция оказывается глубже, чем описан тот тип, который ее определяет - компилятор сообщает об ошибке.

В этом смысле изменений в языке точно не предвидится. Только у меня возникает вопрос: а почему надо обязательно вернуть эту новую функцию? Что, создать, и сразу выполнить с ней все что нужно - нельзя?
with Ada.Text_IO;

procedure Main is

generic
i : Integer;
function Adder(x: integer) return integer;

function Adder(x: integer) return integer is
begin
return x + i;
end Adder;

procedure test(func : access function (X : Integer) return Integer) is
X : integer := 50;
begin
Ada.Text_IO.Put_Line (Integer'Image(func(X)));
end test;

procedure New_Proc (i: integer) is
-- получили функцию с параметрами неизвестными на этапе компиляции.
function My_Adder is new Adder(i);
begin
test (My_Adder'access); -- Выполняем необходимые действия с этой функцией
end New_Proc;

begin
New_Proc(125);
end Main;
 К началу страницы 
+ Ответить 

2 страниц V  1 2 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 29.03.2024 1:55
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name