Oberon space
General Category => Общий раздел => Тема начата: vlad от Март 29, 2013, 03:59:38 pm
-
Смотрим оригинальный репорт (https://github.com/vladfolts/oberonjs/raw/master/doc/Oberon07.Report.pdf) и пытаемся понять, что можно делать со строками (строковыми литералами).
1. объявить CONST
2. использовать в CASE (односимвольные)
3. присвоить в ARRAY N OF CHAR (забив нулями лишние ячейки)
Но нигде не вижу, что строку можно отдать в вызов процедуры. Т.е., WriteLn("Hello, World!") ну никак не написать. Только вот так:
VAR s: ARRAY 16 OF CHAR;
...
s := "Hello, World!";
WriteLn(s);
Можно предположить (из общих соображений), что строки должны автоматом конвертится в открытый ARRAY OF CHAR, причем константный (не VAR). Но в репорте даже намека на это нет (или я не вижу?).
-
Можно предположить (из общих соображений), что строки должны автоматом конвертится в открытый ARRAY OF CHAR, причем константный (не VAR). Но в репорте даже намека на это нет (или я не вижу?).
"If the parameter is a value parameter, the corresponding actual parameter must be an expression."
В каких expression'ах могут участвовать строковые литералы?
-
"If the parameter is a value parameter, the corresponding actual parameter must be an expression."
В каких expression'ах могут участвовать строковые литералы?
В смысле "Hello, World!" - вполне себе expression с точки зрения грамматики. Только тип у этого expression не ARRAY 13 OF CHAR, а хрен знает какой... Поэтому он не соответствует ни одному из возможных типов параметров.
-
"The type of each formal parameter is specified in the parameter list. For variable parameters, it
must be identical to the corresponding actual parameter's type, except in the case of a record,
where it must be a base type of the corresponding actual parameter's type."
Итого, вопрос в том, какой тип у строкового литерала :-) Я предполагаю, что у него спец. тип, который умеет неявно приводиться (да! неявное приведение типов в Обероне!) к чару либо массиву этих самых чаров. Следовательно, вероятно возможно вот такое:
PROCEDURE A(c : CHAR);
PROCEDURE B(a : ARRAY OF CHAR);
...
A("h");
B("h");
С expression'ами вроде понятно - строковый литерал может быть операндом в выражении. Следовательно как VAL-параметр строковый литерал может быть.
Вопрос остаетася может ли строковый литерал быть VAR-параметром? И если нет, то на каком основании. А если да - то что будет если его попробуют поменять?
-
Вопрос остаетася может ли строковый литерал быть VAR-параметром? И если нет, то на каком основании. А если да - то что будет если его попробуют поменять?
Сам задаю вопрос, сам на него отвечаю:
In the case of variable parameters, the actual parameter must be a designator denoting a variable.
If it designates an element of a structured variable, the selector is evaluated when the formal/actual
parameter substitution takes place, i.e. before the execution of the procedure. If the parameter is a
value parameter, the corresponding actual parameter must be an expression.
Все, строковый литерал в качестве VAR-параметра выступать не может, ибо нет переменной.
-
Да, и еще замечание: если наплевать на секцию 9.1. Assignments, то схожая проблема что и со строковыми литералами возникает с NIL'ом. Ибо у NIL'а тоже такой же невнятный тип (даже еще более невнятный!).
Поэтому рабочий вариант видимо такой: использовать для проверки корректности соответствия актуальных и формальных параметров правила присваивания (9.1) на которые накладываются сверху правила из 10.1. В случае противоречий, правила из 10.1 имеют преимущество.
-
Итого, вопрос в том, какой тип у строкового литерала :-) Я предполагаю, что у него спец. тип, который умеет неявно приводиться (да! неявное приведение типов в Обероне!) к чару либо массиву этих самых чаров.
Да, неявное приведение типа в доке по строгому языку смотрится некошерно. Да и уложиться нужно в 16 страниц. Печально все это. Тут уж не до неявных UB...
-
Поэтому рабочий вариант видимо такой: использовать для проверки корректности соответствия актуальных и формальных параметров правила присваивания (9.1) на которые накладываются сверху правила из 10.1. В случае противоречий, правила из 10.1 имеют преимущество.
Присваивание тут тоже не работает - потому что массив в случае параметра открытый. А присваивание прописано только для массивов известной длины. Кроме того, массив - не скалярный тип, а присваивание формальных параметров упоминается только применительно к скалярным типам.
-
Итого, вопрос в том, какой тип у строкового литерала :-) Я предполагаю, что у него спец. тип, который умеет неявно приводиться (да! неявное приведение типов в Обероне!) к чару либо массиву этих самых чаров.
Да, неявное приведение типа в доке по строгому языку смотрится некошерно. Да и уложиться нужно в 16 страниц. Печально все это. Тут уж не до неявных UB...
Самое смешное, что "a" может приводиться и туда и сюда, а вот "aa" - уже нет :-) То есть по факту типы "a" и "aa" отличаются, это два разных типа!
-
Поэтому рабочий вариант видимо такой: использовать для проверки корректности соответствия актуальных и формальных параметров правила присваивания (9.1) на которые накладываются сверху правила из 10.1. В случае противоречий, правила из 10.1 имеют преимущество.
Присваивание тут тоже не работает - потому что массив в случае параметра открытый. А присваивание прописано только для массивов известной длины. Кроме того, массив - не скалярный тип, а присваивание формальных параметров упоминается только применительно к скалярным типам.
Поэтому я и предложил патчить 9.1 посредством 10.1
-
Читаем 9.1:
Strings can be assigned to any array of characters.
Нигде нет упоминания про то, что длина этого array'я должна быть известна.
И кстати, такой вопрос возникает:
MODULE TestModule;
VAR buf : ARRAY 8 OF CHAR;
PROCEDURE Test(VAR s : ARRAY OF CHAR)
BEGIN
s := "01234567890123456789"
END Test
BEGIN
Test(buf)
END TestModule.
Такое работать вообще будет? Или это ошибка компиляции? Или ошибка исполнения? Или что вообще?
-
Дописал еще один пункт:
https://sites.google.com/site/oberonreport/question-list-regarding-to-oberon-07-report-to-be-clarified-by-wirth?pli=1
-
Такое работать вообще будет? Или это ошибка компиляции? Или ошибка исполнения? Или что вообще?
решайте сами... если Вирт явно это не прописал... - значит этот вопрос не важен с точки зрения его видения Оберона.. т.е. как реализатор вы можете выбрать любой путь..
я, например, бы выбрал следующий вариант - ошибка компиляции (предпочтительно), или ошибка времени выполнения..
-
Такое работать вообще будет? Или это ошибка компиляции? Или ошибка исполнения? Или что вообще?
решайте сами... если Вирт явно это не прописал... - значит этот вопрос не важен с точки зрения его видения Оберона.. т.е. как реализатор вы можете выбрать любой путь..
я, например, бы выбрал следующий вариант - ошибка компиляции (предпочтительно), или ошибка времени выполнения..
Проблема в том, что такое решение приведет к созданию диалекта языка. Причем диалекта не совместимого с другими "реализациями". Выходит язык Оберон описан так, что невозможно просто взять и реализовать его, любая реализация автоматически порождает несовместимый диалект в плане даже самых базовых вещей.
-
То есть когда я еще только погружался в описание языка Оберон, я полагал, что да, этот язык as is не годится для прикладного программиста, ибо он не сможет написать на нем даже hello world из за отсутствия в описании языка стандартной библиотеки для ввода-вывода.
Сейчас оказывается, что он не смог бы этого написать даже если бы таковая библиотека была бы описана в сообщении о языке.
-
Такое работать вообще будет? Или это ошибка компиляции? Или ошибка исполнения? Или что вообще?
решайте сами... если Вирт явно это не прописал... - значит этот вопрос не важен с точки зрения его видения Оберона.. т.е. как реализатор вы можете выбрать любой путь..
я, например, бы выбрал следующий вариант - ошибка компиляции (предпочтительно), или ошибка времени выполнения..
Проблема в том, что такое решение приведет к созданию диалекта языка. Причем диалекта не совместимого с другими "реализациями". Выходит язык Оберон описан так, что невозможно просто взять и реализовать его, любая реализация автоматически порождает несовместимый диалект в плане даже самых базовых вещей.
Так я над этим делом и посмеялся в теме про UB... но с другой стороны может в этом и идея Вирта.. заложить основу для родственных DSL...своя реализация под определенные классы микроконтроллеров... - почему бы и нет ?
-
Так я над этим делом и посмеялся в теме про UB... но с другой стороны может в этом и идея Вирта.. заложить основу для родственных DSL...своя реализация под определенные классы микроконтроллеров... - почему бы и нет ?
Откровенно говоря, не вижу тут особого профита с точки зрения микроконтроллеров... Вот именно что в части этих заморочек с типами и строками.
-
Так. У меня ощущение складывается, что проблема есть и просто с массивами:
MODULE TestModule;
VAR intArray : ARRAY 8 OF INTEGER;
PROCEDURE Test(VAR arg : ARRAY OF INTEGER);
VAR localArray : ARRAY 100500 OF INTEGER
BEGIN
arg := localArray
END Test
BEGIN
Test(intArray)
END TestModule.
Что будет? Так можно вообще? Если да, то почему? Если нет, то тоже почему?
-
Откровенно говоря, не вижу тут особого профита с точки зрения микроконтроллеров... Вот именно что в части этих заморочек с типами и строками.
Точно. Такие недосказанности никак не помогают оптимизациям под конкретную железку. Они помогают только уложиться в 16 страниц ;)
-
Так. У меня ощущение складывается, что проблема есть и просто с массивами:
MODULE TestModule;
VAR intArray : ARRAY 8 OF INTEGER;
PROCEDURE Test(VAR arg : ARRAY OF INTEGER);
VAR localArray : ARRAY 100500 OF INTEGER
BEGIN
arg := localArray
END Test
BEGIN
Test(intArray)
END TestModule.
Что будет? Так можно вообще? Если да, то почему? Если нет, то тоже почему?
Ошибка компиляции будет, несовместимость по присваиванию. Массивы должны быть одного типа. Для строк сделано исключение из правила.
-
Так я над этим делом и посмеялся в теме про UB... но с другой стороны может в этом и идея Вирта.. заложить основу для родственных DSL...своя реализация под определенные классы микроконтроллеров... - почему бы и нет ?
Откровенно говоря, не вижу тут особого профита с точки зрения микроконтроллеров... Вот именно что в части этих заморочек с типами и строками.
как гипотеза, профит для разработчиков микроконтроллеров - в том, чтобы быстро забацать DSL на основе оберонных идей, с учетом специфики железа...
-
Так. У меня ощущение складывается, что проблема есть и просто с массивами:
MODULE TestModule;
VAR intArray : ARRAY 8 OF INTEGER;
PROCEDURE Test(VAR arg : ARRAY OF INTEGER);
VAR localArray : ARRAY 100500 OF INTEGER
BEGIN
arg := localArray
END Test
BEGIN
Test(intArray)
END TestModule.
Что будет? Так можно вообще? Если да, то почему? Если нет, то тоже почему?
Ошибка компиляции будет, несовместимость по присваиванию. Массивы должны быть одного типа. Для строк сделано исключение из правила.
OK. Сделаю одного типа:
MODULE TestModule;
VAR
arr1 : ARRAY 8 OF INTEGER;
arr2 : ARRAY 100500 OF INTEGER;
PROCEDURE Test(VAR a, b : ARRAY OF INTEGER);
BEGIN
a := b
END Test
BEGIN
Test(arr1, arr2)
END TestModule.
Лучше? :-)
-
Да, а чтобы не было соблазна просто поменять "указатели" местами, вот уточненный пример:
MODULE TestModule;
VAR arr1 : ARRAY 8 OF INTEGER;
PROCEDURE Test1 (VAR a : ARRAY OF INTEGER);
VAR arr2 : ARRAY 100500 OF INTEGER;
BEGIN
Test2(a, arr2)
END Test1
PROCEDURE Test2 (VAR a, b : ARRAY OF INTEGER);
BEGIN
a:=b
END Test2
BEGIN
Test1(arr1)
END TestModule.
-
Лучше? :-)
а в чем проблемы? - размеры массивов не совпадают, значит присваивание (копирование содержимого) невозможно (строки - исключение)- решение см. выше (ошибка времени компиляции или времени выполнения)
-
Лучше? :-)
а в чем проблемы? - размеры массивов не совпадают, значит присваивание невозможно (строки - исключение)- решение см. выше (ошибка времени компиляции или времени выполнения)
Типы совпадают 1 в 1. На этапе компиляции (особенно раздельной независимой компиляции модулей, как это любят в Обероне) это в принципе не ловится.
-
Лучше? :-)
а в чем проблемы? - размеры массивов не совпадают, значит присваивание невозможно (строки - исключение)- решение см. выше (ошибка времени компиляции или времени выполнения)
Типы совпадают 1 в 1. На этапе компиляции (особенно раздельной независимой компиляции модулей, как это любят в Обероне) это в принципе не ловится.
значит остается второй вариант. (ошибка времени выполнения)
-
Лучше? :-)
а в чем проблемы? - размеры массивов не совпадают, значит присваивание невозможно (строки - исключение)- решение см. выше (ошибка времени компиляции или времени выполнения)
Типы совпадают 1 в 1. На этапе компиляции (особенно раздельной независимой компиляции модулей, как это любят в Обероне) это в принципе не ловится.
значит остается второй вариант. (ошибка времени выполнения)
Ошибки времени исполнения не прописаны в репорте практически никак.
Кроме того, подобное будет постоянно случаться, слишком дырявый язык получается. Программы будут крашится только в путь.
Ну и вообще, не понятно зачем тогда в язык вообще ввели открытые массивы.
-
Открытый массив — это указатель + размер. Размер проверяется во время выполнения. Присваивание a:=b при b большего размера вызовет UB. Правильные программы такого не допустят.
IF LEN(b) <= LEN(a) THEN ... END
-
Лучше? :-)
а в чем проблемы? - размеры массивов не совпадают, значит присваивание невозможно (строки - исключение)- решение см. выше (ошибка времени компиляции или времени выполнения)
Типы совпадают 1 в 1. На этапе компиляции (особенно раздельной независимой компиляции модулей, как это любят в Обероне) это в принципе не ловится.
значит остается второй вариант. (ошибка времени выполнения)
Ошибки времени исполнения не прописаны в репорте практически никак.
Кроме того, подобное будет постоянно случаться, слишком дырявый язык получается. Программы будут крашится только в путь.
Ну и вообще, не понятно зачем тогда в язык вообще ввели открытые массивы.
а что нельзя разве с статическими массивами связать неявные переменные (размеры) - и анализировать их?
-
Открытый массив — это указатель + размер. Размер проверяется во время выполнения. Присваивание a:=b при b большего размера вызовет UB. Правильные программы такого не допустят.
IF LEN(b) <= LEN(a) THEN ... END
необязательно (языком реализация не декларируется)
-
Открытый массив — это указатель + размер. Размер проверяется во время выполнения. Присваивание a:=b при b большего размера вызовет UB. Правильные программы такого не допустят.
IF LEN(b) <= LEN(a) THEN ... END
К сожалению, в сообщении о языке даже UB не прописан (в отличае от того же стандарта С++, где UB прописаны явным образом). Ну и тем более там не прописаны детали реализации всего этого. Например массивы там легко могут банально быть терминированы какой-то специальной меткой (в некоторых ОС и некоторых реализациях это возможно), поэтому будет только указатель.
(если бы Вирт указал в репорте, что LEN(arr) должно работать за O(1) то это существенно увеличило бы шансы того, что открытый массив будет работать именно в виде указателя+длины).
Одной из интерпретаций того, что написано в сообщении о языке, может быть например такое поведение - копируются все, что помещается в другой массив. То что не помещается - просто отбрасывается.
PS. А еще я не понимаю сакраментального смысла наличия процедуры COPY в языке, ведь оно делает ровно то же самое, что и простое присваивание строк.
-
Открытый массив — это указатель + размер.
С указателем это динамический массив.
А открытый массив(параметр)- это массив, с определенным типом элемента и неопределенным(произвольным) размером (тип массива определяется не только типом элемента, но и размерностью)
PROCEDURE (c : ARRAY 2 OF CHAR...
PROCEDURE (c : ARRAY 3 OF CHAR...
PROCEDURE (c : ARRAY 4 OF CHAR...
-
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье.... если это возможно... понятно, что если процедура и и ее вызов по разным модулям это сделать невозможно
-
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье....
Разнеси мои процедуры Test1 и Test2 по разным модулям. И собери эти модули на разных машинах. Откуда там информация в момент компиляции будет?
-
PS. А еще я не понимаю сакраментального смысла наличия процедуры COPY в языке, ведь оно делает ровно то же самое, что и простое присваивание строк.
VAR
a: ARRAY 10 OF CHAR;
b: ARRAY 20 OF CHAR;
...
b := a; (* так нельзя *)
COPY(a, b); (* так можно *)
-
да .. так я и говорю когда это возможно компайл тайм ... нет ран тайм... ошибки
-
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье....
Так не известны - у процедуры в параметрах ОТКРЫТЫЕ массивы, т.е. "безразмерные"
-
PS. А еще я не понимаю сакраментального смысла наличия процедуры COPY в языке, ведь оно делает ровно то же самое, что и простое присваивание строк.
VAR
a: ARRAY 10 OF CHAR;
b: ARRAY 20 OF CHAR;
...
b := a; (* так нельзя *)
COPY(a, b); (* так можно *)
Где про это сказано? В репорте сказано лишь, что оно эквивалентно b:=a.
-
Где про это сказано? В репорте сказано лишь, что оно эквивалентно b:=a.
[/quote]
А где сказано, что b и a в COPY(a, b) должны быть одинакового типа? Так что не совсем эквивалентно.
-
А где сказано, что b и a в COPY(a, b) должны быть одинакового типа? Так что не совсем эквивалентно.
Пожалуй, соглашусь. Правда остается не ясной семантика COPY. По всей видимости она таки должна забивать оставшийся хвост нулями как и в случае с литералом.
Ну и не ясно что будет в случае если мы сделаем COPY(b,a), то есть из большего будем класть в меньшее.
-
Гм. А быть может COPY это просто:
PROCEDURE COPY(VAR a,b ARRAY OF CHAR);
BEGIN
b:=a
END COPY
Но тогда не понятно нафига это было зашивать прямо в язык, ибо либой делается элементарно.
-
Открытый массив — это указатель + размер. Размер проверяется во время выполнения. Присваивание a:=b при b большего размера вызовет UB. Правильные программы такого не допустят.
Суть претензии у valexey (как мне кажется) и у меня в том, что вероятный UB замаскирован за такой атомарной операцией как присваивание. Я в свое время поимел дело с кодом, который бросал исключение в перегруженом операторе =. Это было страшно. Т.е., я бы для копирования массивов отсавил COPY, причем с явным указанием откуда (позиция) и сколько элементов копировать.
-
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье....
Так не известны - у процедуры в параметрах ОТКРЫТЫЕ массивы, т.е. "безразмерные"
ну и что когда можно проверить - компайл - тайм ошибка (если вызов происходит в рамках модуля где определен фактический массив), иначе ран-тайм... абсолютно также вы не сможете определится во время компиляции и с банальным
arr:=m.arr (в секции загрузки основного модуля) если m.arr - определен в некотором модуле m (который вызывается динамически)
-
а в чем проблемы? - размеры массивов не совпадают, значит присваивание невозможно (строки - исключение)- решение см. выше (ошибка времени компиляции или времени выполнения)
Типы совпадают 1 в 1. На этапе компиляции (особенно раздельной независимой компиляции модулей, как это любят в Обероне) это в принципе не ловится.
Здесь статические типы совпадают у формальных параметров в декларации процедуры, а в каждом вызове процедуры в тексте программы статические типы у фактических параметров могут не совпадать и это ловится при компиляции.
Только при интерактивном вызове процедур (через коммандер) статические типы проверяются в начале вызова, и неясно как это интерпретировать, как время компиляции, загрузки или выполнения.
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье... если это возможно... понятно, что если процедура и ее вызов по разным модулям это сделать невозможно
Возможно.
Разнеси мои процедуры Test1 и Test2 по разным модулям. И собери эти модули на разных машинах. Откуда там информация в момент компиляции будет?
Как мне объяснили
http://oberspace.dyndns.org/index.php/topic,158.msg11114.html#msg11114
статические типы переменных из импортируемых модулей берутся при компиляции модуля из символьных файлов импортируемых модулей и копируются их специальные цифровые подписи. При компиляции проверяется и статическая типизация. При загрузке и работе модуля его символьный файл не используется.
Если загружены не те импортируемые модули - с другими символьными файлами - что были при компиляции импортирующего их модуля, то при его загрузке сличение цифровых подписей символьных файлов импортируемых модулей даст ошибку загрузки.
-
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье....
Так не известны - у процедуры в параметрах ОТКРЫТЫЕ массивы, т.е. "безразмерные"
ну и что когда можно проверить - компайл - тайм ошибка (если вызов происходит в рамках модуля где определен фактический массив), иначе ран-тайм... абсолютно также вы не сможете определится во время компиляции и с банальным
arr:=m.arr (в секции загрузки основного модуля) если m.arr - определен в некотором модуле m (который вызывается динамически)
Я говорю о вполне конкретной ситуации - пусть есть процедура, у которой в качестве формальных параметров выступают открытые массивы
PROCEDURE( a, b : ARRAY OF CHAR);
BEGIN
a := b;
END;
в этом случае на этапе компиляции процудуры мы не сможем проверить допустимость присваивания т.к. фп - открытые массивы, т.е. их тип недоопределён в части размерности.
Также мы не сможем (по той же причине) проверить допустимость вызова процедуры с конкретными параметрами. Т.е. здесь сработает проверка только времени выполнения.
НО... к примеру, падение программы в этом случае, когда она выполняется на микроконтроллере, совершенно неверный подход, потому как может привести к непредсказуемым последствиям.
Поэтому в том же Активном Обероне и его предках выбрана другая стратегия - присваивания возможны всегда, но будет скопировано столько, сколько влезет в массив-приемник, без всяких трапов и остановов. И это правильная стратегия.
-
Не понимаю а в чем проблема... динамических массивов нет, размеры известны на этапе компиляции, проверяй себе на здоровье....
Так не известны - у процедуры в параметрах ОТКРЫТЫЕ массивы, т.е. "безразмерные"
ну и что когда можно проверить - компайл - тайм ошибка (если вызов происходит в рамках модуля где определен фактический массив), иначе ран-тайм... абсолютно также вы не сможете определится во время компиляции и с банальным
arr:=m.arr (в секции загрузки основного модуля) если m.arr - определен в некотором модуле m (который вызывается динамически)
Я говорю о вполне конкретной ситуации - пусть есть процедура, у которой в качестве формальных параметров выступают открытые массивы
PROCEDURE( a, b : ARRAY OF CHAR);
BEGIN
a := b;
END;
в этом случае на этапе компиляции процудуры мы не сможем проверить допустимость присваивания т.к. фп - открытые массивы, т.е. их тип недоопределён в части размерности.
Также мы не сможем (по той же причине) проверить допустимость вызова процедуры с конкретными параметрами. Т.е. здесь сработает проверка только времени выполнения.
НО... к примеру, падение программы в этом случае, когда она выполняется на микроконтроллере, совершенно неверный подход, потому как может привести к непредсказуемым последствиям.
Поэтому в том же Активном Обероне и его предках выбрана другая стратегия - присваивания возможны всегда, но будет скопировано столько, сколько влезет в массив-приемник, без всяких трапов и остановов. И это правильная стратегия.
Понял.. вы просто говорите про ДРУГУЮ возможность реализации - почему бы и нет .. если , как говорится это makes the difference... просто, с моей точки зрения, вылет программы одинаково одинаково нежелателен - будь он вследствие деления на ноль, или неаккуратной работой с памятью. Но все- таки , если не трудно поясните почему невозможно в принципе проверить на этапе компиляции КОНКРЕТНЫЙ вызов этой функции (с конкретными параметрами) - ибо размеры фактических параметров(количество элементов в передаваемых массивах) известны на этапе компиляции..
-
кстати, правильно ли я понял, что фактическую длину строки хранящейся в массиве символов считать приходится ручками?
-
кстати, правильно ли я понял, что фактическую длину строки хранящейся в массиве символов считать приходится ручками?
Смотря где. В Astrobe есть встроенная функция LENGTH, работает аналогично функции strlen си.
-
в стандарте О7... verily.
-
Но все- таки , если не трудно поясните почему невозможно в принципе проверить на этапе компиляции КОНКРЕТНЫЙ вызов этой функции (с конкретными параметрами) - ибо размеры фактических параметров(количество элементов в передаваемых массивах) известны на этапе компиляции..
эээ, мы же говорим об открытых массивах в качестве формальных параметров.
а открытые массивы потому и открытые, что их определение не завершено, это, если можно так сказать, обобщённые массивы, без них пришлось бы на каждую размерность писать свою персональную процедуру,
PROCEDURE( a, b : ARRAY 2 OF CHAR )
PROCEDURE( a, b : ARRAY 3 OF CHAR )
вместо этого мы пишем обобщенную процедуру
PROCEDURE( a, b : ARRAY OF CHAR )
Соответственно и длины массивов формальных параметров при компиляции процедуры типа
PROCEDURE( a, b : ARRAY OF CHAR );
BEGIN
a := b;
END
в присваивании мы проверить не сможем, потому что тип - открытый массив, у которых длину во время компиляции узнать невозможно в принципе, по причине отсутствия.
При вызове такой процедуры на этапе компиляции мы также ничего проконтролировать не сможем, иначе теряется смысл введения параметров-открытых(обобщённых) массивов.
Поэтому и остаётся или контроль в рантайме с трапами/остановами или копировать столько, сколько влезет.
-
Поэтому в том же Активном Обероне и его предках выбрана другая стратегия - присваивания возможны всегда, но будет скопировано столько, сколько влезет в массив-приемник, без всяких трапов и остановов. И это правильная стратегия.
Правильная стратегия - это когда после присваивания слева получается то же, что и справа. Все остальные варианты поведения делают сопровождающему программисту плохо :) С тем же успехом можно разрешить присваивание VAR параметров рекордов базовых типов с автоматическим привидением к полному типу и падением/игнорированием, если типы не совпадают.
Применительно к открытым массивам присваивание можно было бы разрешить, если массив мог менять свой размер. Тогда слева получался бы такой же массив как и справа (с тем же размером), без падений и удивлений на тему "а если больше, а если меньше".
-
Применительно к открытым массивам присваивание можно было бы разрешить, если массив мог менять свой размер.
это было бы глупо, потому-что параметр-открытый массив это фактически статический массив, тип которого определён и известен на этапе компиляции.
Изменение размера - это изменение типа массива, что идля статического типа мягко говоря неправильно.
Ну и как физически изменить размер статического массива? Память под него выделена однократно и её размер фиксирован.
Открытый массив это же не динамический массив
-
это было бы глупо, потому-что параметр-открытый массив это фактически статический массив, тип которого определён и известен на этапе компиляции.
Изменение размера - это изменение типа массива, что идля статического типа мягко говоря неправильно.
Ну и как физически изменить размер статического массива? Память под него выделена однократно и её размер фиксирован.
Открытый массив это же не динамический массив
Ну вот. Раз так, то нефиг вообще разрешать присваивание. Я к тому и клонил. Вообще попробуй придумать практическую задачу, где нужно "приравнять" только начало массива. Я вот не могу такую придумать.
- Массив либо копируется целиком (подразумевается, что размеры равны, и если нет - то это ошибка, которую хочется диагностировать).
- Либо копируется расчетный диапазон (и выход диапазона за пределы массивов тоже хочется диагностировать).
- Либо копируется массивная сущность целиком (вместе с размером, будь он меньше или больше) - но этот вариант мы отбросили.
P.S. Кстати, на моей практике как раз чаще всего встречается последний вариант. Так что вообще всю идею неизменности размера массива (при невозможность по месту создать новый массив нужно размера) я считаю осмысленной только с точки зрения микроконтроллеров.
-
При вызове такой процедуры на этапе компиляции мы также ничего проконтролировать не сможем, иначе теряется смысл введения параметров-открытых(обобщённых) массивов.
это я слышал, но ни как не могу понять в чем выражается эта потеря..- разве есть осмысленные варианты присваивания массивов разных размеров (если это не массив символов)
-
и еще более внимательно посмотрел на ваш вариант процедуры.. от оригинала Алексея он отличается отсутствием VAR... вопрос в этом случае следует создавать локальные копии фактических массивов или нет?
-
и еще более внимательно посмотрел на ваш вариант процедуры.. от оригинала Алексея он отличается отсутствием VAR... вопрос в этом случае следует создавать локальные копии фактических массивов или нет?
Это я ошибся, там должен быть VAR, конечно.
-
При вызове такой процедуры на этапе компиляции мы также ничего проконтролировать не сможем, иначе теряется смысл введения параметров-открытых(обобщённых) массивов.
это я слышал, но ни как не могу понять в чем выражается эта потеря..- разве есть осмысленные варианты присваивания массивов разных размеров (если это не массив символов)
Потеря чего? Смысла введения параметров-открытых массивов?
Так они и были введены для того, чтобы можно было в одну процедуру передавать массивы без привязки к длине, главное чтобы тип элементов совпадал.
Большого смысла присваивать массивы разной длины нет, тем более что это в Оберонах запрещено, потому что тип массивов в этом случае не совпадёт ( тип массива определяется типом элемента и размерностью ).
Но тип открытого массива определяется только типом его элементов. Поэтому на этапе компиляции проверяется только это соответствие. Соответствие длин мы узнаем только в точке присваивания в момент выполнения, а что при этом делать - валиться с трапом или скопировать максимально возможное количество элементов - это уже детали реализации.
-
(если это не массив символов)
мы о массивах символов и говорим
-
(если это не массив символов)
мы о массивах символов и говорим.
ну нет Алексей, переключился на массивы целых чисел....
-
Но тип открытого массива определяется только типом его элементов.
НЕТ, в моем понимании, понятия типа открытого массива - есть передача массива в процедуру, использующая семантику открытого массива (открытый массив - это не тип).
-
Но тип открытого массива определяется только типом его элементов.
НЕТ, в моем понимании, понятия типа открытого массива - есть передача массива в процедуру, использующая семантику открытого массива (открытый массив - это не тип).
Это тип формального параметра.
-
Но тип открытого массива определяется только типом его элементов.
НЕТ, в моем понимании, понятия типа открытого массива - есть передача массива в процедуру, использующая семантику открытого массива (открытый массив - это не тип).
Это тип формального параметра.
Забавно, всю жизнь считал что это правила, по которым интерпретируются фактически переданные массивы... не больше, но и не меньше :)
-
Забавно, всю жизнь считал что это правила, по которым интерпретируются фактически переданные массивы... не больше, но и не меньше :)
Ну тип, наверное, можно назвать правилами интерпретации
-
Забавно, всю жизнь считал что это правила, по которым интерпретируются фактически переданные массивы... не больше, но и не меньше :)
Ну тип, наверное, можно назвать правилами интерпретации
Можно, но нужно ли... стандартное определение (императивные яву)- это схема по которой создаются переменные, определяющая диапазон хранимых значений и операции над ними.
-
Забавно, всю жизнь считал что это правила, по которым интерпретируются фактически переданные массивы... не больше, но и не меньше :)
Ну тип, наверное, можно назвать правилами интерпретации
Можно, но нужно ли... стандартное определение (императивные яву)- это схема по которой создаются переменные, определяющая диапазон хранимых значений и операции над ними.
это чем-то отличается от правил интерпретации? по-моему это они и есть )
-
это чем-то отличается от правил интерпретации? по-моему это они и есть )
Разумеется есть.. и в частности они проявляются в моих с вами разночтениях.. - я рассматриваю массив передаваемый по семантике открытого.. как нормально определенный массив.. имеющий тип фактического параметра.. - и соответственно, никаких потерь смысла.. в моем понимании (при возможном контроле компилятором его размера) нет.
-
я рассматриваю массив передаваемый по семантике открытого.. как нормально определенный массив..
естественно, что фактический параметр это и есть "нормальный" массив, т.е. определённый по всем правилам, к примеру, статический массив, у которого определённы тип элементов и размерность, или динамический, у которого на этапе компиляции определён только тип элементов.
Да, кстати, возникает вопрос - как на этапе компиляции контролировать размер динамических массивов? Так же как и у открытых - никак. Только во время исполнения.
-
я рассматриваю массив передаваемый по семантике открытого.. как нормально определенный массив..
естественно, что фактический параметр это и есть "нормальный" массив, т.е. определённый по всем правилам, к примеру, статический массив, у которого определённы тип элементов и размерность, или динамический, у которого на этапе компиляции определён только тип элементов.
Да, кстати, возникает вопрос - как на этапе компиляции контролировать размер динамических массивов? Так же как и у открытых - никак. Только во время исполнения.
тык весь попс то и заключается в том, что в O7 (сабже) динамических массивов нет...
-
то есть вы в принципе не сможете передать динамический массив по семантике открытого (вследствие отсутствия оного)
-
тык весь попс то и заключается в том, что в O7 (сабже) динамических массивов нет...
а это не важно, потому что в данном случае у них одинаковая проблема - отсутствие возможности проконтролировать размер во время компиляции, я специально упомянул динамические массивы, чтобы стало понятно, почему на этапе компиляции нет возможности контролировать длину ФОРМАЛЬНОГО параметра-открытого массива, но при этом динамические массивы спокойно передаются в качестве ФАКТИЧЕСКИХ параметров в процедуры с формальными параметрами в виде открытых массивов.
Ведь понятно, что формальные и фактические параметры это разные вещи.
И если формальные параметры это открытый массив, то при компиляции такой процедуры (которая(компиляция) происходит один раз) у типа формального параметра - открытого массива - длина не известна, а значит и нет совершенно никакой возможности проконтролировать соответствие длины массива на этапе компиляции, блин, это же очевидно, я не понимаю, о чём спор на несколько страниц 0 нет там такой информации.
Вызов же данной процедуры с ФАКТИЧЕСКИМИ параметрами, размер которых может быть известен (а может и не быть) на этапе компиляции, совершенно никак не меняет дело, потому что, по понятным причинам, вызов процедуры и её реализация компилируются раздельно, но даже если бы они как-то компилировались "совместно" это никак бы не изменило ситуацию, потому что формальный параметр открытый массив может принимать фактический параметр любого размера с совместимым типом элементов.%?*?%%%% что здесь может быть непонятного, какие разночнения могут быть
-
Ладно, Дизер, я понял - Вы прикалываетесь, типа воскресенье, скучно...
Потому что иначе этот бессмысленный спор ни о чём объяснить невозможно
-
Ладно, Дизер, я понял - Вы прикалываетесь, типа воскресенье, скучно...
Потому что иначе этот бессмысленный спор ни о чём объяснить невозможно
отчасти.. но также, я считаю что, по крайней мере, если все сущности и вызовы процедуры находятся в рамках одного модуля - проверить присваивание можно...
-
В общем случае даже в рамках одного модуля сложно с точки зрения компилятора или невозможно вообще.
VAR a, b, c: открытый массив;
...
Joke := Random();
IF Joke = 1 THEN a:=b ELSIF Joke = 2 THEN a:=c ELSE c:=b END;
-
В общем случае даже в рамках одного модуля сложно с точки зрения компилятора или невозможно вообще.
VAR a, b, c: открытый массив;
...
Joke := Random();
IF Joke = 1 THEN a:=b ELSIF Joke = 2 THEN a:=c ELSE c:=b END;
вы впадаете в ошибку Кемета... открытый массив ЭТО НЕ ТИП ДАННЫХ... это СОГЛАШЕНИЕ о синтаксических правилах и интерпретации передачи ОБЫЧНЫХ массивов в подпрограмму.
-
отчасти.. но также, я считаю что, по крайней мере, если все сущности и вызовы процедуры находятся в рамках одного модуля - проверить присваивание можно...
Как? Вот простой пример:
PROCEDURE Assign( VAR a, b : ARRAY OF CHAR );
BEGIN
a := b;
END Assign;
Как здесь проверить "правильность" присваивания? Ведь как раз исходя из семантики открытого массива это присваивание всегда допустимо.
Вообще если нужно проконтролировать "правильность" присваивания, то использование для этого открытых массивов совершенно неверный подход, они как раз создавались совершенно для другого - чтобы обойти такую проверку на уровне компиляции.
Нужно использовать пользовательский тип
PROCEDURE Assign( VAR a, b : MyArrayType );
BEGIN
a := b;
END Assign;
что и обеспечит проверку уровня компиляции.
Или на этапе компиляции вручную сравнивать размер
PROCEDURE Assign( VAR a, b : ARRAY OF CHAR );
BEGIN
IF LEN( a ) = LEN( b ) THEN
a := b;
ELSE
...
END;
END Assign;
И будет щасте
-
вы впадаете в ошибку Кемета...
Да с чего бы я впадал в ошибку, я Вам говорю, что это тип ФОРМАЛЬНОГО параметра, а не тип переменной. Переменных такого типа нет (может быть указатель на открытый массив). Это специальный тип, как NIL, например
-
отчасти.. но также, я считаю что, по крайней мере, если все сущности и вызовы процедуры находятся в рамках одного модуля - проверить присваивание можно...
Как? Вот простой пример:
PROCEDURE Assign( VAR a, b : ARRAY OF CHAR );
BEGIN
a := b;
END Assign;
Как здесь проверить "правильность" присваивания? Ведь как раз исходя из семантики открытого массива это присваивание всегда допустимо.
Вообще если нужно проконтролировать "правильность" присваивания, то использование для этого открытых массивов совершенно неверный подход, они как раз создавались совершенно для другого - чтобы обойти такую проверку на уровне компиляции.
проверяется не определение функции - c ним все ОК, а ее вызов в этом же модуле Assign(A,B); - A,B - фактические массивы.
-
PROCEDURE Test (VAR a, b, c: ARRAY OF INTEGER);
VAR
Joke: INTEGER;
BEGIN
Joke := Random();
IF Joke = 1 THEN a:=b ELSIF Joke = 2 THEN a:=c ELSE c:=b END;
END;
VAR
a: ARRAY 3 OF INTEGER;
b: ARRAY 4 OF INTEGER;
c: ARRAY 5 OF INTEGER;
BEGIN
Test(a, b, c); // Как проверить правильность вызова?
END Module.
-
А в чем проблема... ни одно из присваиваний в процедуре в данном вызове не валидно. (и БЕЗ РАЗНИЦЫ выполняется код конкретного присваивания или нет), компилируемый текст есть в наличии, размеры массивов известны (тут ... достаточно просто проверить все присваивания в ТЕКСТЕ процедуры)... другое дело, если эта процедура была бы определена в другом (откомпилированном модуле), а вызывалась бы в текущем (но я и НЕ УТВЕРЖДАЛ, что подобная проверка ВСЕГДА возможна) -я говорил, что оптимально будет если это возможно , то компайл тайм, если нет - рантайм.... впрочем я в 3 раз повторяюсь.
-
Ну вот и не соглашусь с вами.
PROCEDURE Random (): INTEGER;
BEGIN
RETURN 3;
END Random;
И код должен компилироваться. В противном случае функциональность открытых массивов несправедливо урезается, вдобавок ещё и завязывается на проверки в рамках только одного модуля. Это очень странно. Наконец, если процедура вызывает процедуру, которая вызывает процедуру, то вся информация о начальных размерах потеряется (или придётся анализировать в глубину).
-
Ну вот и не соглашусь с вами.
PROCEDURE Random (): INTEGER;
BEGIN
RETURN 3;
END Random;
И код должен компилироваться. В противном случае функциональность открытых массивов несправедливо урезается, вдобавок ещё и завязывается на проверки в рамках только одного модуля. Это очень странно. Наконец, если процедура вызывает процедуру, которая вызывает процедуру, то вся информация о начальных размерах потеряется (или придётся анализировать в глубину).
Что урезается ? - с процедурой (все ОК) , а вот вызов ее с неверными параметрами в данном случае можно определить во время компиляции..
-
http://www.ocp.inf.ethz.ch/forum/index.php/topic,744.0.html
-
http://www.ocp.inf.ethz.ch/forum/index.php/topic,744.0.html
one more viewpoint...that's a bit boring isn't it...