Oberon space
General Category => Общий раздел => Тема начата: vlad от Август 27, 2013, 05:04:25 pm
-
В порядке разминки - давно правильны циклов не было :)
Итак, на входе массив массивов и разделитель. Надо все это объединить в одну последовательность. Т.е.: [[1, 2, 3], [4,5]], 10 -> [1, 2, 3, 10, 4, 5]
Экспериментировать можно прямо здесь: http://oberspace.dyndns.org/oberonjs.html
PROCEDURE do(input: ARRAY OF ARRAY OF INTEGER; separator: INTEGER);
...
P.S. Чувствую ЦД где-то рядом ;)
-
Мда, господа, пытаюсь сейчас решить эту задачку и прямо вижу -- не взлетит Оберон-07. Ни на десктопе, ни в вебе )))
Даёшь дженерики! Даёшь инициализацию массивов!! Даёшь динамические массивы!!! )))
-
Мда, господа, пытаюсь сейчас решить эту задачку и прямо вижу -- не взлетит Оберон-07. Ни на десктопе, ни в вебе )))
Даёшь дженерики! Даёшь инициализацию массивов!! Даёшь динамические массивы!!! )))
Хм, а ведь akron1 написал на этом языке редактор для оберона и компилятор. Прямо титанический труд ))
-
Даёшь дженерики! Даёшь инициализацию массивов!! Даёшь динамические массивы!!! )))
Да, собственно я тоже стал представлять как это сделать... И решил запостить ;)
-
Легко:
static int[] doCS(int[][] input, int separator) {
int len = input.Select(m => m.Length).Sum() + input.Length - 1;
int[] res = new int[len];
int i = 0;
bool first = true;
foreach (var m in input) {
if (first) {
first = false;
} else {
res[i++] = separator;
}
foreach (var x in m) {
res[i++] = x;
}
}
return res;
}
Шутка :)
-
Пусть тот код, который составил такой входной массив составит таким же способом массив для хранения результатов. ;D
-
Итак, на входе массив массивов и разделитель.
ARRAY OF ARRAY OF INTEGER это не массив массивов, а двумерный массив. В оберонах массив массивов это
ARRAY OF POINTER TO ARRAY OF INTEGER. Да, в репорте O7 нет указателей на массивы и динамических массивов, ну значит их следует добавить, на практике они нужны.
Даёшь дженерики! Даёшь инициализацию массивов!! Даёшь динамические массивы!!! )))
С динамическими массивами все понятно, а про дженерики много разговоров, но пока я не видел описание синтаксиса и семантики дженериков для оберона. Возможно, следует обсудить синтаксис и семантику дженериков (я в этом вопросе слабо разбираюсь).
-
Если для общения с внешним миром Оберону будет достаточно открытых массивов, то внутри рантайма можно ведь обойтись и без динамических массивов.
-
ARRAY OF ARRAY OF INTEGER это не массив массивов, а двумерный массив.
Да, действительно, хотя размерности явно не указаны, но они будут одинаковы для всех элементов.
С динамическими массивами все понятно, а про дженерики много разговоров, но пока я не видел описание синтаксиса и семантики дженериков для оберона. Возможно, следует обсудить синтаксис и семантику дженериков (я в этом вопросе слабо разбираюсь).
Дженерики с собой сразу тащут много всего...
-
А могут ли встречаться пустые массивы?
-
А могут ли встречаться пустые массивы?
array of тип и есть пустой массив. То есть память не распределена.
-
Пример на free pascal
{$mode objfpc}{$H+}
program main;
var
M: array of integer;
begin
WriteLn(Length(M));
end.
Ответ 0
-
В порядке разминки - давно правильны циклов не было :)
Итак, на входе массив массивов и разделитель. Надо все это объединить в одну последовательность. Т.е.: [[1, 2, 3], [4,5]], 10 -> [1, 2, 3, 10, 4, 5]
Экспериментировать можно прямо здесь: http://oberspace.dyndns.org/oberonjs.html
PROCEDURE do(input: ARRAY OF ARRAY OF INTEGER; separator: INTEGER);
...
Итак, на входе массив массивов и разделитель.
ARRAY OF ARRAY OF INTEGER это не массив массивов, а двумерный массив. В оберонах массив массивов это
ARRAY OF POINTER TO ARRAY OF INTEGER. Да, в репорте O7 нет указателей на массивы и динамических массивов, ну значит их следует добавить, на практике они нужны.
Вы оба не правы :-)
Массив по определению - это (упорядоченное)множество элементов одного типа. Соответственно массив массивов - это массив массивов ОДНОГО типа, а ARRAY 24 OF INTEGER и ARRAY 42 OF INTEGER - это два разных типа. Следовательно массив массивов всегда эквивалентен прямому произведению оных массивов. Ну, в частном случае это будет просто двумерный массив.
Но, с другой стороны, то что написал в примере Влад ([[1, 2, 3], [4,5]]) не является массивом массивов (длины массивов разные). То есть таки да, ARRAY OF ARRAY OF INTEGER не годится.
Указатель на массив для получения того что требуется, также не нужно вводить в язык. Все делается ведь элементарно:
...
Как именно делается элементарно пока не покажу - в компиляторе обнаружился баг :-)
-
А могут ли встречаться пустые массивы?
Репорт традиционно молчит. В моей реализации - нет, будет ошибка компиляции при попытке объявить нулевой массив.
-
А зачем? Никто ведь не мешает обойти массив в том порядке, который нужен.
Потому что иначе, по причине отсутствия динамических массивов, простой реализации не получится, придётся городить что-то подобное:
TYPE
Chunk = POINTER TO ChunkDesc;
ChunkDesc = RECORD next : Chunk; END;
Chunk1024 = POINTER TO Chunk1024Desc;
Chunk1024Desc = RECORD( ChunkDesc ) value: ARRAY 1024 OF INTEGER; END;
Chunk512 = POINTER TO Chunk512Desc;
Chunk512Desc = RECORD( ChunkDesc ) value: ARRAY 512 OF INTEGER; END;
...
ChunkXXX = POINTER TO ChunkXXXDesc;
ChunkXXXDesc = RECORD( ChunkDesk ) value : ARRAY XXX OF INTEGER; END;
LIST = Chunk;
Или вообще, каждый элемент оборачивать. Но в любом случае, чтобы получить динамику, придётся городить списковые структуры или даже деревья.
-
Легко:
...
Шутка :)
Ну раз пошёл такой оффтоп, то и я не удержусь: :P
concat'intersperse :: a -> [[a]] -> [a]
concat'intersperse _ [] = []
concat'intersperse sep (xs:[]) = xs
concat'intersperse sep (xs:xss) = xs ++ sep:concat'intersperse sep xss
main = do
print $ concat'intersperse 10 []
print $ concat'intersperse 10 [[]]
print $ concat'intersperse 10 [[1,2,3]]
print $ concat'intersperse 10 [[1,2,3], [4,5]]
print $ concat'intersperse 10 [[1,2,3], [4,5], [6]]
Main> :main
[]
[]
[1,2,3]
[1,2,3,10,4,5]
[1,2,3,10,4,5,10,6]
-
Легко:
...
Шутка :)
Ну раз пошёл такой оффтоп, то и я не удержусь: :P
concat'intersperse :: a -> [[a]] -> [a]
concat'intersperse _ [] = []
concat'intersperse sep (xs:[]) = xs
concat'intersperse sep (xs:xss) = xs ++ sep:concat'intersperse sep xss
main = do
print $ concat'intersperse 10 []
print $ concat'intersperse 10 [[]]
print $ concat'intersperse 10 [[1,2,3]]
print $ concat'intersperse 10 [[1,2,3], [4,5]]
print $ concat'intersperse 10 [[1,2,3], [4,5], [6]]
Main> :main
[]
[]
[1,2,3]
[1,2,3,10,4,5]
[1,2,3,10,4,5,10,6]
Э, нет. На списках каждый дурак даже на обероне-07 может. А ты на массивах, на массивах давай! То есть ArrayList (а не список!) массивов причем все массивы разной длины.
-
array of тип и есть пустой массив. То есть память не распределена.
Точнее, память распределена только под указатель (изначально NIL).
-
Ну раз пошёл такой оффтоп, то и я не удержусь: :P
concat'intersperse :: a -> [[a]] -> [a]
concat'intersperse _ [] = []
concat'intersperse sep (xs:[]) = xs
concat'intersperse sep (xs:xss) = xs ++ sep:concat'intersperse sep xss
main = do
print $ concat'intersperse 10 []
print $ concat'intersperse 10 [[]]
print $ concat'intersperse 10 [[1,2,3]]
print $ concat'intersperse 10 [[1,2,3], [4,5]]
print $ concat'intersperse 10 [[1,2,3], [4,5], [6]]
Main> :main
[]
[]
[1,2,3]
[1,2,3,10,4,5]
[1,2,3,10,4,5,10,6]
Э, нет. На списках каждый дурак даже на обероне-07 может. А ты на массивах, на массивах давай! То есть ArrayList (а не список!) массивов причем все массивы разной длины.
Да, и без левых расширизмов, вроде тех же существовательных типов, пожалуйста. Ведь мы тут пишем на чистом Обероне-07, без расширизмов, вот и ты давай на чистом Haskell'e, без ghc-расширизмов :-)
-
Э, нет. На списках каждый дурак даже на обероне-07 может. А ты на массивах, на массивах давай! То есть ArrayList (а не список!) массивов причем все массивы разной длины.
Я даже не помню как работать с массивами на хаскелле -- это же неидеоматично для него )))
-
Э, нет. На списках каждый дурак даже на обероне-07 может. А ты на массивах, на массивах давай! То есть ArrayList (а не список!) массивов причем все массивы разной длины.
Я даже не помню как работать с массивами на хаскелле -- это же неидеоматично для него )))
Ну вот, для Оберона-07 тоже не идиоматично использовать массив как контейнер общего назначения :-) В Обероне-07 массив - это строительный блок для структур данных (контейнеров), ну и для всякой мелочи, вроде локальных буферов.
-
Ну раз пошёл такой оффтоп, то и я не удержусь: :P
concat'intersperse :: a -> [[a]] -> [a]
concat'intersperse _ [] = []
concat'intersperse sep (xs:[]) = xs
concat'intersperse sep (xs:xss) = xs ++ sep:concat'intersperse sep xss
Чо ж я так перемудрил-то? Ведь в самом придуманном мною имени функции подсказка к её реализации:
import List
concat'intersperse :: a -> [[a]] -> [a]
concat'intersperse sep xss = concat $ intersperse [sep] xss
main = do
print $ concat'intersperse 10 []
print $ concat'intersperse 10 [[]]
print $ concat'intersperse 10 [[1,2,3]]
print $ concat'intersperse 10 [[1,2,3], [4,5]]
print $ concat'intersperse 10 [[1,2,3], [4,5], [6]]
print $ concat'intersperse ' ' ["qwerty", "asdf", "zxc"]
Main> :main
[]
[]
[1,2,3]
[1,2,3,10,4,5]
[1,2,3,10,4,5,10,6]
"qwerty asdf zxc"
-
Ну вот, для Оберона-07 тоже не идиоматично использовать массив как контейнер общего назначения :-) В Обероне-07 массив - это строительный блок для структур данных (контейнеров), ну и для всякой мелочи, вроде локальных буферов.
Так в самом языке Хаскелл нет даже такого понятия как массив. Это всего лишь одна из стандартных библиотек. Чтобы создать масcив массивов с содержимым [[1,2,3], [4,5], [6]] надо такой код громоздить:
arr = array (0, 2) [ (0, array (0, 2) [(0, 1), (1, 2), (2, 3)])
, (1, array (0, 1) [(0, 4), (1, 5)])
, (2, array (0, 0) [(0, 6)])
]
-
Товарищи, подскажите. В седьмом объероне можно так?
PROCEDURE Do(p: INTEGER);
VAR
r: POINTER TO RECORD
a: ARRAY p OF INTEGER;
END;
BEGIN
END Do;
В репорте вроде так...
...
length = ConstExpression.
ConstExpression = expression...
-
Товарищи, подскажите. В седьмом объероне можно так?
PROCEDURE Do(p: INTEGER);
VAR
r: POINTER TO RECORD
a: ARRAY p OF INTEGER;
END;
BEGIN
END Do;
В репорте вроде так...
...
length = ConstExpression.
ConstExpression = expression...
p ведь не константа. Нельзя так. И в C++ так нельзя. А вот в C99 - можно.
-
Так там expression без ограничений.
Где в репорте ты видишь такой запрет?
У меня сейчас разрыв шаблона... :)
Я всегда думал что в седьмом обероне динамика именно так и делается...
-
Так там expression без ограничений.
Где в репорте ты видишь такой запрет?
У меня сейчас разрыв шаблона... :)
Я всегда думал что в седьмом обероне динамика именно так и делается...
Какой смысл вводить ConstExpression если он просто эквивалентен expression? :-) (ConstExpression = expression. )
В репорте есть некая неопределенность что именно считать const expression'ом, однако в том месте в котором у тебя заминка, разночтений быть не может:
A constant expression can be evaluated by a mere textual scan without actually executing the
program.
Твой пример не позволяет на этапе компиляции (без исполнения программы) вычислить 'p', а следовательно и длину массива.
-
PROCEDURE Planarize(a: Arrs; delimeter: INTEGER): Arr;
VAR b, tmp: Arr;
i, j, k, len: INTEGER;
BEGIN
i := 0; len := 0;
WHILE i < LEN(a) DO
len := len + LEN(a[i]);
i := i + 1
END;
NEW( b, len * 2 - 1 );
i := 0;
k := 0;
WHILE i < LEN( a ) DO
tmp := a[i];
j := 0;
WHILE j < LEN( tmp ) DO
b[k] := tmp[j];
j := j + 1;
k := k + 2
END;
i := i + 1
END;
i := 1;
WHILE i < LEN( b ) DO
b[i] := delimeter;
i := i + 2
END;
RETURN b
END Planarize;
-
PROCEDURE Planarize(a: Arrs; delimeter: INTEGER): Arr;
VAR b, tmp: Arr;
i, j, k, len: INTEGER;
BEGIN
i := 0; len := 0;
WHILE i < LEN(a) DO
len := len + LEN(a[i]);
i := i + 1
END;
NEW( b, len * 2 - 1 );
i := 0;
k := 0;
WHILE i < LEN( a ) DO
tmp := a[i];
j := 0;
WHILE j < LEN( tmp ) DO
b[k] := tmp[j];
j := j + 1;
k := k + 2
END;
i := i + 1
END;
i := 1;
WHILE i < LEN( b ) DO
b[i] := delimeter;
i := i + 2
END;
RETURN b
END Planarize;
А что такое Arr и Arrs? Собственно в Обероне-07 вся фишка в работе с типами. Алгоритмы то тривиальны.
-
PROCEDURE Planarize(a: Arrs; delimeter: INTEGER): Arr;
VAR b, tmp: Arr;
i, j, k, len: INTEGER;
BEGIN
i := 0; len := 0;
WHILE i < LEN(a) DO
len := len + LEN(a[i]);
i := i + 1
END;
NEW( b, len * 2 - 1 );
i := 0;
k := 0;
WHILE i < LEN( a ) DO
tmp := a[i];
j := 0;
WHILE j < LEN( tmp ) DO
b[k] := tmp[j];
j := j + 1;
k := k + 2
END;
i := i + 1
END;
i := 1;
WHILE i < LEN( b ) DO
b[i] := delimeter;
i := i + 2
END;
RETURN b
END Planarize;
А Вы проверяли этот код? Можете привести описания типов Arr и Arrs?
А то что я ни пытаюсь изобразить, ни онлайн-компилятор OberonJS, ни компилятор от akron1'а не хотят принимать их...
-
В репорте есть некая неопределенность что именно считать const expression'ом, однако в том месте в котором у тебя заминка, разночтений быть не может:
A constant expression can be evaluated by a mere textual scan without actually executing the
program.
Твой пример не позволяет на этапе компиляции (без исполнения программы) вычислить 'p', а следовательно и длину массива.
Я думал это относится только к Constant declarations.
-
А что такое Arr и Arrs? Собственно в Обероне-07 вся фишка в работе с типами. Алгоритмы то тривиальны.
Arr не может быть массивом, так как процедура в Обероне-07 не может вернуть массив в качестве значения. С другой стороны, указателем на массив Arr тоже быть не может? По мнению компилятора akron1'а, по крайней мере...
-
считайте, что это Оберон 89 : ).
А для 07 нужен особый модуль. Для вывода данных. Например, Channels. В нём с помощью низкоуровневых средств может создаваться выходной канал (массив произвольной длины, например).
-
А что такое Arr и Arrs? Собственно в Обероне-07 вся фишка в работе с типами. Алгоритмы то тривиальны.
Arr не может быть массивом, так как процедура в Обероне-07 не может вернуть массив в качестве значения. С другой стороны, указателем на массив Arr тоже быть не может? По мнению компилятора akron1'а, по крайней мере...
Arrs = POINTER TO ARRAY OF POINTER TO ARRAY OF INTEGER;
Arr = POINTER TO ARRAY OF INTEGER;
-
А что такое Arr и Arrs? Собственно в Обероне-07 вся фишка в работе с типами. Алгоритмы то тривиальны.
Arr не может быть массивом, так как процедура в Обероне-07 не может вернуть массив в качестве значения. С другой стороны, указателем на массив Arr тоже быть не может? По мнению компилятора akron1'а, по крайней мере...
Arrs = POINTER TO ARRAY OF POINTER TO ARRAY OF INTEGER;
Arr = POINTER TO ARRAY OF INTEGER;
POINTER TO ARRAY OF POINTER TO ARRAY OF INTEGER; - не бывает
Arr = POINTER TO ARRAY OF INTEGER; - тоже не бывает.
-
POINTER TO ARRAY OF POINTER TO ARRAY OF INTEGER; - не бывает
Arr = POINTER TO ARRAY OF INTEGER; - тоже не бывает.
Вообще, какие полезные массивные типы там могут быть-то хоть?
-
Слушайте, народ, че то я не врубаюсь. А как без динамических массивов кодить то? O_o
Вот например хочу прочитать из файла массив строк. Естественно что ни длина массива ни длины строк заранее неизвестны. Как их в памяти то разместить?
-
Слушайте, народ, че то я не врубаюсь. А как без динамических массивов кодить то? O_o
Вот например хочу прочитать из файла массив строк. Естественно что ни длина массива ни длины строк заранее неизвестны. Как их в памяти то разместить?
Через любую динамическую структуру данных. Например список чанков, или vlist какой-нибудь.
-
Т.е. окромя списка никак? Жесть однако.
-
function concat(input, separator)
local result = {}
function foo(input, result)
for _, v in ipairs(input) do
if type(v) == 'table' then
foo(v, result)
else
result[#result+1] = v
end
end
end
foo(input, result)
return table.concat(result, separator)
end
local arr = {{{1, 2, 3}, {4,5}}, 10}
print(concat(arr, ', '))
-
Тьху блин. Так там разделитель 10?
Походу я не понял задачу...
-
Слушайте, народ, че то я не врубаюсь. А как без динамических массивов кодить то? O_o
Вот например хочу прочитать из файла массив строк. Естественно что ни длина массива ни длины строк заранее неизвестны. Как их в памяти то разместить?
Через любую динамическую структуру данных. Например список чанков, или vlist какой-нибудь.
Вот он минимализм. В процессорах начиная с pentium появилась технология предвыборка данных.
http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%B2%D1%8B%D0%B1%D0%BE%D1%80%D0%BA%D0%B0_%D0%BA%D0%BE%D0%B4%D0%B0
Предвыборка кода — это запрос процессора в оперативную память для считывания инструкций заблаговременно, до того момента как эти инструкции потребуется исполнять. В результате этого запроса, инструкции загружаются из памяти в кэш. Когда инструкции, потребуется исполнять, доступ к ним будет осуществляться значительно быстрее, т.к. задержка при обращении в кэш на порядки меньше, чем при обращении в оперативную паять.
Получается данный пласт оптимизации, не будет задействован. То есть только на статике.
Т.е. окромя списка никак? Жесть однако.
Уверен, что да, жесть. Бывает для задачи проще массив, чем список, потом следить за указателями и т.д
А ещё проще делать массив указателей.
-
Стоп. А как динамические строки использовать?
CONST
MAX_STRING = 255;
VAR
String: ARRAY MAX_STRING OF CHAR;
Или делать строки на списках. Объединение будет быстрым. А вот проход будет постоянным, кэш промахом.
-
Слишком низкоуровневым язык получился. ИМХО.
-
Слишком низкоуровневым язык получился. ИМХО.
Ну, скажем так - без стандартной либы и дополнительного инструментария для разработки, этот язык слабо пригоден для прикладного программиста.
-
Вот он минимализм. В процессорах начиная с pentium появилась технология предвыборка данных.
http://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%B2%D1%8B%D0%B1%D0%BE%D1%80%D0%BA%D0%B0_%D0%BA%D0%BE%D0%B4%D0%B0
Во-первых, это предвыборка кода, а во-вторых, на Яве есть сторонняя библиотека (называется как-то типа Ropes), производительность которой выше, чем над стандартными строками именно потому, что внутреннее представление строк там в виде дерева (вроде) из подстрок (возможно, даже, массивов).
-
Слишком низкоуровневым язык получился. ИМХО.
Смотря где его применять. Для ПЛИС, например, вполне нормально.
-
Такс. Набросал пример решения (не претендуя на алгоритмическую гениальность и кошерность циклов) с применением прототипа макета черновика стандартной либы :-)
(поскольку это прототип, погонять в онлайн-компиляторе пока не выйдет)
Да, для полноты картины я реализовал обе фунции - и ту которая создает входные данные и ту которая уже слепливает "массивы" в один с разделителями.
MODULE VladQuest;
IMPORT VectorInt, ArrayInt;
PROCEDURE Merge(input: ARRAY OF VectorInt.T; separator: INTEGER) : VectorInt.T;
VAR
res : VectorInt.T;
i,j : INTEGER;
BEGIN
res := VectorInt.Create;
FOR i:=0 TO LEN(input) DO
FOR j:=0 TO VectorInt.Len(input[i]) DO
VectorInt.PushBack(res,VectorInt.Get(input[i],j))
END;
VectorInt.PushBack(res, separator)
END
VectorInt.PopBack(res);
RETURN res
END Merge;
PROCEDURE Test;
VAR
input : ARRAY 2 OF ArrayInt.T;
BEGIN
ArrayInt.Fill2(input,
VectorInt.Make3(1,2,3),
VectorInt.Make2(4,5));
Merge(input, 10);
END Test;
END VladQuest.
Возможен вопрос - а что если мне не нравятся такие длиные имена у функций (VectorInt.PusgBack), что если хочется короче и лаконичней? Не проблема, можно сделать псевдонимы (хотя возможность именно такого рода псевдонимов, удобный таких, прямо сейчас горячо обсуждается в конфе :-) ):
MODULE VladQuest;
IMPORT VectorInt, ArrayInt;
CONST
Create = VectorInt.Create;
Len = VectorInt.Len;
PushBack = VectorInt.PushBack;
PopBack = VectorInt.PopBack;
Get = VectorInt.Get;
Make3 = VectorInt.Make3;
Make2 = VectorInt.Make2;
Fill2 = ArrayInt.Fill2;
PROCEDURE Merge(input: ARRAY OF VectorInt.T; separator: INTEGER) : VectorInt.T;
VAR
res : VectorInt.T;
i,j : INTEGER;
BEGIN
res := Create;
FOR i:=0 TO LEN(input) DO
FOR j:=0 TO Len(input[i]) DO
PushBack(res,Get(input[i],j))
END;
PushBack(res, separator)
END
PopBack(res);
RETURN res
END Merge;
PROCEDURE Test;
VAR
input : ARRAY 2 OF ArrayInt.T;
BEGIN
ArrayInt.Fill2(input,
Make3(1,2,3),
Make2(4,5));
Merge(input, 10);
END Test;
END VladQuest.
-
Так. Налажал таки. IMPORT ArrayInt следует заменить на IMPORT ArrayVectorInt;
Ну и соответственно ArrayInt.Fill2 на ArrayVectorInt.Fill2
-
Для контраста питоновский вариант:
a = [[1, 2, 3], [4,5]]
sep = 10
reduce(lambda x, y: x + [sep] + y, a)
Выводит:
[1, 2, 3, 10, 4, 5]
-
CONST
Create = VectorInt.Create;
Len = VectorInt.Len;
PushBack = VectorInt.PushBack;
PopBack = VectorInt.PopBack;
Get = VectorInt.Get;
Make3 = VectorInt.Make3;
Make2 = VectorInt.Make2;
Мне не кажется это хорошим решением. Псевдонимы нужны не только для процедур, но и для переменных и типов. Объявление CONST будет выглядеть странно (даже если формально (!) это не противоречит репорту). Если уж расширять язык, то лучше, наверное, разделить объявление собственно констант и псевдонимов. Может быть так:
MODULE Foo;
IMPORT Out;
ALIAS
outs = Out.String;
...
CONST
...
TYPE
...
VAR
...
BEGIN
...
END Foo.
-
CONST
Create = VectorInt.Create;
Len = VectorInt.Len;
PushBack = VectorInt.PushBack;
PopBack = VectorInt.PopBack;
Get = VectorInt.Get;
Make3 = VectorInt.Make3;
Make2 = VectorInt.Make2;
Мне не кажется это хорошим решением. Псевдонимы нужны не только для процедур, но и для переменных и типов. Объявление CONST будет выглядеть странно (даже если формально (!) это не противоречит репорту). Если уж расширять язык, то лучше, наверное, разделить объявление собственно констант и псевдонимов. Может быть так:
MODULE Foo;
IMPORT Out;
ALIAS
outs = Out.String;
...
CONST
...
TYPE
...
VAR
...
BEGIN
...
END Foo.
Штука в том, что я не собираюсь расширять язык. Зачем его расширять, если там все есть и так? :-)
Вообще, с константами в Обероне большая беда. Там это весьма мутное понятие. И это предмет отдельного разговора, чтобы договориться и уточнить что под этим подразумевается.
-
зачем? чем это лучше, c точки зрения наглядности:
IMPORT
OutS:=Out.String,
...
-
Вообще, с константами в Обероне большая беда. Там это весьма мутное понятие. И это предмет отдельного разговора, чтобы договориться и уточнить что под этим подразумевается.
то что вы предлагаете ясности не привносит, по - любому.
-
зачем? чем это лучше, c точки зрения наглядности:
IMPORT
OutS:=Out.String,
...
Это ж не валидная конструкция в Обероне.
-
Вообще, с константами в Обероне большая беда. Там это весьма мутное понятие. И это предмет отдельного разговора, чтобы договориться и уточнить что под этим подразумевается.
то что вы предлагаете ясности не привносит, по - любому.
Я предлагаю лишь обсудить, и показываю варианты толкования.
-
зачем? чем это лучше, c точки зрения наглядности:
IMPORT
OutS:=Out.String,
...
Это ж не валидная конструкция в Обероне.
почему, просто это работает только для модулей (вообще говоря, я комментировал предложение Акрона по поводу добавления секции ALIAS - c точки зрения репорта она один черт невалидна - просто вы успели вставить сообщение раньше).
-
т.е. просто расширение предполагает возможность создания псевдонима на любую импортируемую сущность (а не только модули)
-
Как уже предлагал в конференции, сделать по типу Модулы-3:
FROM ModuleName IMPORT X, Y, Z, P := Proc, P1 := Proc1;
-
Но вообще, лично я предпочитаю видеть квалификатор модуля в имени переменной/процедуры, потому что сразу понятно, что это и зачем.
-
Как уже предлагал в конференции, сделать по типу Модулы-3:
FROM ModuleName IMPORT X, Y, Z, P := Proc, P1 := Proc1;
неплохо , но требует расширения синтаксиса, как и в случае с алиасом.
-
res := VectorInt.Create;
Так, а разве в Обероне при вызове функции скобки не являются обязательными? В КП без скобок можно вызывать только процедуры.
-
Как уже предлагал в конференции, сделать по типу Модулы-3:
FROM ModuleName IMPORT X, Y, Z, P := Proc, P1 := Proc1;
неплохо , но требует расширения синтаксиса, как и в случае с алиасом.
Так это ещё в Модуле-2 было, Вирт от этого отказался в обероне в пользу явной квалификации без исключений...
-
res := VectorInt.Create;
Так, а разве в Обероне при вызове функции скобки не являются обязательными? В КП без скобок можно вызывать только процедуры.
Это называется непротестированный код )))
-
Как уже предлагал в конференции, сделать по типу Модулы-3:
FROM ModuleName IMPORT X, Y, Z, P := Proc, P1 := Proc1;
неплохо , но требует расширения синтаксиса, как и в случае с алиасом.
Это не важно, главное, что ни один из предложенных вариантов не будет компилироваться ни одним компилятором любого из Оберонов.
И если уж мы решили расширить язык, то в данном случае лучше расширить синтаксически, чем семантически. Потому что перегруженная семантика совершенно не очевидна.
-
res := VectorInt.Create;
Так, а разве в Обероне при вызове функции скобки не являются обязательными? В КП без скобок можно вызывать только процедуры.
Являются. Иначе была бы при подобном вызове функции которая возвращает процедурный тип. Так что это мой ляп.
Плюс у меня там еще один ляп:
Merge(input, 10);
Вызов функции без созранения возвращенного значения.
-
Как уже предлагал в конференции, сделать по типу Модулы-3:
FROM ModuleName IMPORT X, Y, Z, P := Proc, P1 := Proc1;
неплохо , но требует расширения синтаксиса, как и в случае с алиасом.
Это не важно, главное, что ни один из предложенных вариантов не будет компилироваться ни одним компилятором любого из Оберонов.
Возможно лишь потому, что они не до конца и не правильно интерпретируют Oberon-report? :-)
Вопрос не в добавлении расширизма на самом деле. Вопрос в уточнении репорта, ибо этот момент (могут ли быть константы процедурного типа). Но это конечно отдельная тема.
И если уж мы решили расширить язык, то в данном случае лучше расширить синтаксически, чем семантически. Потому что перегруженная семантика совершенно не очевидна.
Нет, не решили. Речь идет о уточнении семантики актуального оберон-репорта. Без оглядки на то, какие традиции сложились вокруг реализаций других оберонов.
-
Вообще, народ, я этот пример приводил не за ради этих несчастных CONST'ов (они второстепенны), а чтобы показать как примерно будет писаться код с использованием стандартной либы. То есть показать примерно как я себе вижу оную стандартную библиотеку в разрезе контейнеров.
Я правильно понимаю, что возражений, замечаний и вопросов нет?