![]() |
1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!
![]() ![]() |
![]() |
TarasBer |
![]()
Сообщение
#1
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
И что делать с этим raised CONSTRAINT_ERROR : test.adb:24 discriminant check failed ? В процедуре через out-параметр присвоилось нормально, однако. А вот t3'access.all := t1'access.all; - ошибка дискриминанта Почему прямо присваивать можно, а через указатель - нельзя? Так и написано в стандарте? Если поставить точку останова, а потом добить пустых строчек так, чтобы эта точка оказалась на строчке, на которой ничего нет, а потом отрубить отладчик, пересобрать код, перезапустить отладчик, то эту точку останова уже не убрать. Дизассмеблер не взлетел: Couldn't get assembly code. Кстати, смысла на ограничения параметров в функциях нет никакого. Избавление от побочных эффектов? Ха, толку, если можно писать во внешние переменные. Зато костыль с access получится на славу по уродливости. Зачем вообще языки Паскалевого семейства делают ненужное разделение на процедуры и функции? Да, концепция красивая, типа процедура - то, что выполняется, функция - то, что возвращает значение, но в условиях реальности она только мешает. Сообщение отредактировано: TarasBer - 31.01.2011 15:11 -------------------- |
volvo |
![]()
Сообщение
#2
|
Гость ![]() |
Цитата И что делать с этим Думать, прежде, чем писать такие вещи. Ибо компилятор на 100% прав. Смотри ,что происходит: до тех пор, пока ты пользуешься копированием вида t1 := t2 - компилятор не проверяет легальность такого копирования, он просто берет и копирует все содержимое одной записи в другую. А вот когда ты делаешь ссылками - тут все становится гораздо интереснее. Компилятор сначала проверит, а имеешь ли ты право это сделать, совпадает ли дискриминант. И только когда совпадает - все пройдет без выброса исключения. Смотри:raised CONSTRAINT_ERROR : test.adb:24 discriminant check failed function set(t: access tmain) return boolean is Цитата Кстати, смысла на ограничения параметров в функциях нет никакого. Правильно. Поэтому Стандарт Ada 2012 отменяет это ограничение. Как только он будет окончательно принят и будет создан компилятор, полностью поддерживающий новый Стандарт - можно будет пользоваться in out параметрами и в функциях.Цитата Дизассмеблер не взлетел: Couldn't get assembly code. У меня тоже так показывает. Ровно до того момента, как программа будет запущена. Запустил - получаю код в окошке Assembly. Я надеюсь в настройках проекта Switches -> Ada Linker не стоит галка на Strip symbols? Если стоит - то не будет ни Assembly, ни отображения регистров процессора. |
TarasBer |
![]()
Сообщение
#3
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
> Компилятор сначала проверит, а имеешь ли ты право это сделать, совпадает ли дискриминант. И только когда совпадает - все пройдет без выброса исключения.
Только я так и не понял, почему он прав и нафига он это проверяет? И что, главное, делать с этим? Мне суппресс дискриминанта лепить? (и значение дискриминанта по умолчанию выставить на самую длиную ветку, а то он, кажется, память по разному выделяет указателям на структуры с разным дискриминантом) > Я надеюсь в настройках проекта Switches -> Ada Linker не стоит галка на Strip symbols? Галочки у меня там не стоит, регистры показываются, дизассемблер - нет. -------------------- |
volvo |
![]()
Сообщение
#4
|
Гость ![]() |
Цитата Только я так и не понял, почему он прав и нафига он это проверяет? Значит, тебе не нужна Ада. Используй С и действуй без проверок. А писать на одном языке в стиле другого - это значит заранее обрекать проект на провал. Проверяет - потому что работа со ссылочными типами контролируется гораздо серьезнее, чем работа с типами обычными. Кстати, я бы добавил еще и ограничение по простому присваиванию дискриминантных записей. Разные дискриминанты - до свидания, получите Constraint_Error безо всяких разговоров (если не отключался контроль).Цитата И что, главное, делать с этим? Да, но не глобально, а локально, только в функции, где происходит копирование:Мне суппресс дискриминанта лепить? function set(t: access tmain) return boolean is . Теперь при помощи этой функции любые записи могут присваиваться друг другу (предупреждаю сразу: я бы так не делал - чревато ошибками. На простых типах полей может и отработать, на сложных начнутся глюки. Я вообще стараюсь Suppress-ы не использовать). В других частях кода останется поведение по-умолчанию. |
-TarasBer- |
![]()
Сообщение
#5
|
Гость ![]() |
Мне всего-то надо создать в куче сущность с дискриминантом, неизвестным на этапе компиляции. И чтобы значение этой сущности устанавливала функция через
> Кстати, я бы добавил еще и ограничение по простому присваиванию дискриминантных записей. Тогда они теряют смысл. Особенно, если value for discriminant must be static. > Да, но не глобально, а локально, только в функции, где происходит копирование: Ну я локально и сделал, но уродство получается. Я тоже не считаю, что подавление - это нормальное решение. А контроль мне нужен, чтобы не использовать случайно сущности не по назначению (то есть не в соответствии с дискриминантом). Но мне нужна и возможность на ходу изменять назначение. Так-то я могу забить на дискриминант, написать через структуры, у которых используются 3 параметра из 10 (а чё, я привык после ВинАПИ), но это ж не круто, интересно всё-таки изучить этот момент и что из него можно выжать легально (без затыкания рта контролёру). |
volvo |
![]()
Сообщение
#6
|
Гость ![]() |
Цитата Тогда они теряют смысл. Особенно, если value for discriminant must be static. Я сказал на операцию присваивания, а не на операцию инициализации:a := (d => 0, f1 => 1); Еще раз возвращаемся к тому, зачем были созданы записи с вариантами вообще и дискриминантные - в частности. Затем, чтобы контролировать, имеешь ли ты в данный конкретный момент (для установленного дискриминанта) обращаться к данному конкретному полю, или нет. А теперь см. сюда: with ada.Text_IO; Как думаешь, что будет выведено на экран? Не запуская программу попробуй ответить... Вот как раз тогда, когда ты работаешь через access-параметры, контроль именно такой, каким должен быть. Цитата Но мне нужна и возможность на ходу изменять назначение. Меняй. По правилам языка, а не по своим правилам, и не так, как ты привык это делать в других языках. По правилам Ады, чтобы сменить назначение записи (т.е., изменить значение дискриминанта), ты должен при помощи агрегата установить новый дискриминант и ВСЕ соответствующие ему поля. Только тогда ты сможешь избежать того, что я пытался показать тебе вышеприведенной программой. |
TarasBer |
![]()
Сообщение
#7
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
> Затем, чтобы контролировать, имеешь ли ты в данный конкретный момент (для установленного дискриминанта) обращаться к данному конкретному полю, или нет.
Правильно, мне это как раз даже нужно, мне этого реально не хватало в Дельфи. > b := (d => 0, f1 => 1); -- Это - нет А если я не знаю (на этапе компиляции), какое именно d мне понадобится?
Нет, спасибо. > Как думаешь, что будет выведено на экран? Не запуская программу попробуй ответить... t2.f2 и t2.f3 не должны вывестись вообще, но если заставить, то будет Код 1 1 2 1 Во второй строке 1, а не 2, потому что его затёрло поле f1, находящееся по этому же адресу. (я угадал? Программу не запускал) Не вижу в этом примере ничего опасного. Программа должна срезаться при попытке вывести t2.f2 и t2.f3. А в присваивании нет ничего такого. t2.f1 будет честно равно единице. > ты должен при помощи агрегата установить новый дискриминант и ВСЕ соответствующие ему поля. А если я не знаю новое значение дискриминанта на этапе компиляции? Добавлено через 3 мин. Кстати, как сдвинуть выделенный текст вправо-влево (аналог ctrl+k+i, ctrl+k+u)? -------------------- |
volvo |
![]()
Сообщение
#8
|
Гость ![]() |
Цитата А если я не знаю (на этапе компиляции), какое именно d мне понадобится? Пожалуйста. Только тебе это не поможет - ты все равно получишь Constraint_Error. Выбор у тебя невелик. Либо отказаться от использования discriminant records и решить задачу по-другому, либо воспользоваться procedure вместо function (это тоже не будет работать со всеми вариантами, см. ниже), либо отключать проверку дискриминанта. Ну, и четвертый вариант: ждать выхода компилятора, полностью поддерживающего Ada 2012.<...> Нет, спасибо. Ада тебе не позволит никакими ухищрениями обойти контроль дискриминанта в любом объекте, расположенном в куче, либо вообще в любом объекте, если ты обращаешься к нему через ссылку. Обрати внимание: procedure Main is Контроль можно только отключить. Хочешь - отключай (если уверен, что это не приведет в дальнейшем к проблемам). Цитата Кстати, как сдвинуть выделенный текст вправо-влево (аналог ctrl+k+i, ctrl+k+u)? Без понятия. Не требовалось ни разу, у меня на сохранение файла повешено его переформатирование, каждый раз когда я жму Ctrl+S, исходник приводится к тому виду, который я установил в "Pretty Printer" в настройках проекта. Потом при проверке стиля проблем гораздо меньше.Можно сделать такое форматирование вручную, Edit -> Pretty Print. |
TarasBer |
![]()
Сообщение
#9
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
> Либо отказаться от использования 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 -------------------- |
volvo |
![]()
Сообщение
#10
|
Гость ![]() |
Цитата для записей с дискриминантом по умолчанию, как написано, в стандарте, память всегда выделяется под самую длинную ветку. В Стандарте? Где именно, можно уточнить? Ибо это не выполняется ни разу. Проверь, чему равен t1'Size, а чему - t2'Size (где t1 имеет дискриминант = 0, а t2 - дискриминант = 1). А ведь использование этого поля не ограничивается обычным селектором. Я ж могу и так сделать:type Vector is array(Positive range <>) of Integer; , и это тоже дискриминантная запись. Какой теперь будет размер у 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." В итоговой версии документа этого предложения уже нет, не вышло оно из драфта. Причины непонятны. |
TarasBer |
![]()
Сообщение
#11
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
> В Стандарте? Где именно, можно уточнить? Ибо это не выполняется ни разу.
Ну не в стандарте, а в учебнике (если я правильно его понял): ![]() Компилятор интересно ругнулся на попытку написать if i in value1 | value2 сказал что-то типа "это будет доступно в 2012 году". Это так и есть? Ещё я заметил, что можно создавать локальные шаблонные функции, инициализируя их параметрами, неизвестными на этапе компиляции. Жаль только, что с этими функциями ничего такого больше делать нельзя, а ведь лямбды и генерация кода по ходу выполнения были так близко... Ещё я заметил, что в стандартных модулях нету моднявой записи SomeObject.SomeMethod(parameters), есть только тёплая ламповая SomeMethod(SomeObject, parameters), это потому, что решили не добавлять этого в язык? Короче, я тут родил, пока изучал язык, небольшую программу (калькулятор с разбором выражений), если интересно: ![]() В целом, язык оставил впечатление, как очень простой и минималистичный. Я не знаю, почему Вирту и Хоару он показался сложным, наверное, он для своего времени был слишком крут. -------------------- |
volvo |
![]()
Сообщение
#12
|
Гость ![]() |
Цитата это потому, что решили не добавлять этого в язык? Оно уже сейчас есть в языке. Но только в А2005, а как должен читать код человек, только что пришедший с А95? Там ведь так нельзя было делать. В целях удобства пользователей это делается. С точки зрения компилятора эти 2 типа записи абсолютно одинаковы.Цитата Ну не в стандарте, а в учебнике (если я правильно его понял): Не совсем. Тут размер еще зависит от способа описания переменной. То есть, если ты описываешь переменную так, что ее дискриминант становится постоянным и не допустимо его дальнейшее изменение (для этого достаточно написать v : TMain(0); скажем), то размер записи будет равен размеру жестко установленного варианта. Если же переменная описана с возможностью изменения дискриминанта, то размер ее будет равен размеру ее максимального варианта. с этим аккуратнее будь. И учти, что в A95 (если компилируешь без ключа -gnat05) у aliased-записи нельзя было менять дискриминант вообще, в то время как у обычной - согласно общим правилам. То есть, t13 : aliased TMain1 := (d => 0, f1 => 1); В 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. Проект чуть позже посмотрю, хорошо? |
TarasBer |
![]()
Сообщение
#13
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
> С точки зрения компилятора эти 2 типа записи абсолютно одинаковы.
Странно, у меня не вышло (стоит режим 2005, с 83 и 95 галочки сняты). Говорит, "неверный префикс". Или это потому, что я не трогал объявление функции? А как тогда объявлять надо? > Кроме этого должны быть разрешены Case-выражения, типа А они позволят писать что-то типа y := (case b is when true => cos, when false => sin)(x)? И почему нету end case? Красивее и логичнее бы смотрелось с end case и без внешних скобок, была бы унификация с имеющимся case, то есть просто было бы надаление case свойством возвращать значения. > Вирт был обижен, что не его поделку выбрали в качестве базы для нового языка Модула-2? А почему "поделка"? -------------------- |
volvo |
![]()
Сообщение
#14
|
Гость ![]() |
Я не про Модулу в данном случае. Я про тот проект, который они предоставили на обсуждение комиссии, выбравшей четырех претендентов. Этот проект был основан на Алголе и был откровенно слабым, Вирт его упростил до предела, что потом неоднократно делал со всеми своими проектами, включая Оберон и Компонентный Паскаль (Вирт и потом говорил, что "для сложных задач должны быть простые решения", но то что у него получилось в конкурсе было слишком просто и не удовлетворяло условиям)
Цитата А они позволят писать что-то типа Подождем окончательной реализации. Я бы пока сказал "не планируется". С синтаксисом надо уточнить, но по моему в описании этой фичи как раз не было end caseЦитата Странно, у меня не вышло (стоит режим 2005, с 83 и 95 галочки сняты). Говорит, "неверный префикс" Тип должен быть теговым и объявляться в другом пакете:Ads: type X is tagged record Adb: procedure P(Obj : in out X; Value : Integer) is Использование: with MyRec; use MyRec; |
-TarasBer- |
![]()
Сообщение
#15
|
Гость ![]() |
> Я не про Модулу в данном случае. Я про тот проект, который они предоставили на обсуждение комиссии, выбравшей четырех претендентов. Этот проект был основан на Алголе и был откровенно слабым, Вирт его упростил до предела, что потом неоднократно делал со всеми своими проектами, включая Оберон и Компонентный Паскаль (Вирт и потом говорил, что "для сложных задач должны быть простые решения", но то что у него получилось в конкурсе было слишком просто и не удовлетворяло условиям)
А как назывался-то? Я в Википедии не могу найти что-то упоминания о проекте Вирта. |
volvo |
![]()
Сообщение
#16
|
Гость ![]() |
Не знаю, было ли у того проекта отдельное название, ведь группа Вирта не вошла даже в финальную "цветную" четверку (Красный, Желтый, Зеленый и Синий), а вылетела раньше. Но Вирт продвигал там идеи Алгол-W, того самого, которым он в свое время предлагал заменить Алгол-60, и после НЕутверждения которого Вирт обрушился с критикой на "Комитет по стандартизации Алгола". История повторилась, его проект опять не выбрали, и опять он начал критиковать все предложения, продолжающие соревноваться между собой. По ходу, неудачник он какой-то...
|
-TarasBer- |
![]()
Сообщение
#17
|
Гость ![]() |
> Но Вирт продвигал там идеи Алгол-W
Почитал в английской википедии. Мне понравилось, что одно слово для процедур и функций, а то зачем для слова для одинаковой сущности вводить? > По ходу, неудачник он какой-то... Ну не знаю, одна удача у него есть, самая главная (Паскаль), и хватит. Много удач одному человеку не положено. > История повторилась, его проект опять не выбрали, и опять он начал критиковать все предложения, продолжающие соревноваться между собой. Ну так делать не стоит, да, но с кем не бывает? А в стандарте-2012 будут лямбды и всякие возможности на ходу генерировать функции? (мои попытки локально сгенерировать шаблонную функцию на основе входных параметров и передать наружу обломались). А то вот Дельфи в 2009 ввели, С++0х всё вводят, как бы не отстать. |
volvo |
![]()
Сообщение
#18
|
Гость ![]() |
Цитата мои попытки локально сгенерировать шаблонную функцию на основе входных параметров и передать наружу обломались Что именно ты пробовал сделать, можно посмотреть? И, заодно, как именно ты хочешь это использовать. Я к тому, что использованию шаблонной функции должна предшествовать ее инстанциация определенным типом/значением/функцией. |
TarasBer |
![]()
Сообщение
#19
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
Ну классический пример (из http://8vmr.livejournal.com/6114.html пункт 2):
Может и это кажется надуманным, но все технологии поначалу такими кажутся. -------------------- |
volvo |
![]()
Сообщение
#20
|
Гость ![]() |
Стоп. Ада такого не позволит по одной простой причине: на момент выхода из New_Func вложенная функция прекратит существование. Это отслеживается компилятором, и как только функция оказывается глубже, чем описан тот тип, который ее определяет - компилятор сообщает об ошибке.
В этом смысле изменений в языке точно не предвидится. Только у меня возникает вопрос: а почему надо обязательно вернуть эту новую функцию? Что, создать, и сразу выполнить с ней все что нужно - нельзя? with Ada.Text_IO; |
![]() ![]() |
![]() |
Текстовая версия | 24.06.2025 10:50 |