Просмотр сообщений

В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.


Сообщения - vlad

Страницы: 1 ... 90 91 [92] 93
1366
А в питоне разве содержимое кортэжа мутабельно?
Собственно у питона две беды -- динамическая типизация и мутабельность данных :-)

Да, динамическая типизация усугубляет. Но у меня и в С++ такая же проблема. Начинает ходить такая тупла с двумя int. И фиг сходу скажешь - чего ж там за int'ы и какой из них тебе нужен.

Цитировать
Скажем в haskell'a я часто пользуюсь кортежами, и проблем с пониманием того, что там лежит обычно не возникает -- типизация то строгая статическая.

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

1367
1.Необходимость больше писать приведёт к тому, что фишкой не будут пользоваться. Перепишите пример со структурами и сравните. Вспомните хотя бы, как сишники жалуются на "многословность" синтаксиса Оберона.

Ну вот я пишу на питоне тоже, там есть родные (лаконичные) кортежи. Пользуюсь ими все равно не очень часто (хотя пишу в обсуждаемом стиле - все инициализируется чем-то осмысленным). Основной недостаток - если такой кортеж пошел гулять за пределы двух/трех функций, то понять смысл того, что там лежит становится трудно. Именованная структура все же лучше. Опять же - ваш оригинальный пример довольно экстремальный :) Так что острой необходимости в кортежах я не вижу.

Цитата: Comdiv
2.Как минимум нужно и объявление типа по месту.

В смысле рядом с функцией? Ну да, желательно. Но тоже не то, чтобы принципиально, если модули человеческих размеров.

Цитата: Comdiv
Цитировать
Чего ж там сложного??? Компилятор уже умеет иметь дело с временными переменными (для вычисления выражений). Объявление по месту - такая же временная переменная.
Не знаю, не пробовал реализовать, но интуитивно чувствую, что не очень это просто для понимания компилятора, когда группу чего-то отдельного, можно представить как одно и наоборот.

Для понимания компилятора там самое сложное - разобраться с областями видимости. А так.. не знаю... ИМХО все просто.

Цитата: Comdiv
Тернарный оператор намного проще, особенно если не как в С, а как-то так :
Цитировать
TOP(condition, value1, value2);

Ну такая функция все равно будет встроенной, так что не знаю, ИМХО не должно быть трудностей.

Цитата: Comdiv
Правильнее было сказать: статически объявленные экземпляры структур, т.е. не в динамической памяти (затрудняюсь более грамотно сформулировать)

Ну так - инициализировать при объявлении. Что не так?

Цитата: Comdiv
Цитировать
Не. Можно без конструкторов. Просто синтаксис для инициализации рекордов. Если полей много - делается обычная вспомогательная функция-конструктор. Ничего в язык добавлять не надо.
Точно ничего? А выделять память отдельной операцией будете? Чем поможет вспомогательная функция-конструктор, если инициализировать всё равно одной командой нужно? Как инициализировать расширенные записи при желании использовать код для базовых записей?

Ну, допустим у нас есть такой синтаксис для инициализации:
TYPE X = RECORD a: INTEGER; b: INTEGER; END
...
VAR x:= X{1, 2}; // локальная переменная

Выделение в хипе:
VAR x:= NEW(X{1, 2});

Функция-конструктор:
PROCEDURE construct_x(): X
BEGIN
    RETURN X{1, 2};
END construct_x

Расширение записи (Y наследуется от X с добавлением одного поля):
VAR y:= Y{X{1, 2}, 3}; // локальная переменная

Использование функции конструктора:
PROCEDURE construct_y(): Y
BEGIN
    RETURN Y{construct_x(), 3};
END construct_y

Цитировать
Тем не менее, данные могут гарантировано инициализироваться в секции инициализации, но они всё равно должны объявляться через optional. Это точно не влечёт дополнительных расходов со стороны программиста и программы в виде явных и неявных проверок/приведений типа?

А. Понял. Нет. Просто данные модуля инициализируются так же как и локальные переменные - при объявлении. Инициализация таких данных происходит до вызова секции инициализации модуля.

Цитировать
К примеру, транспонирование матрицы - штука быстрая. А если это массив структур, содержащих массивы?

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

Цитировать
Правильное. Не могу припомнить сколь-нибудь серьёзную проблему, связанную именно с неинициализированной переменной, а вот функции по нескольку тысяч строк, плохо поддающиеся пониманию и переработке из-за усеянности на самом деле ненужными return-ами мне встречаются регулярно.

Дык, согласитесь, что оригинальная проблема в функциях на 1000 строк, а не в RETURN. Думаю вы бы скорее согласились сопровождать функции на 10 строк с RETURN, чем на 1000 строк без RETURN? ;)

Цитировать
Я бы и не хотел, чтобы компилятор вопил по этому поводу. Это должно остаться на уровне стороннего анализатора. А помимо компилятора, код просматривает и человек, вот тут-то мы и выигрываем.

Человеком ваш код тоже воспринимается непросто. Лично мне понятнее переделанный вариант.


1368
Общий раздел / Re:Оберон в образовании.
« : Февраль 23, 2011, 06:46:49 pm »
Согласен с Ильёй. OUT-параметры вполне органично могут применяться и безболезненно применяются. Неприязнь к ним - просто особенность восприятия или привычка конкретных людей. Кроме того, сама природа функций подразумевает в большинстве случаев возможность не возвратить корректный результат, так что математическая нотация в случае корректной работы с подпрограммами не может использоваться часто.

С функциями, которые возвращают некорректный результат жить очень трудно. Тратить учебное время непрофильных специальностей на объяснение несовершенства компьютерного мира и методы борьбы с ними (коды ошибок, механизм исключений) - ИМХО не очень эффективно. Проще сказать, что результат всегда корректен, а если он никак не может быть получен - лепить ASSERT/HALT. Для учебных целей - вполне хватит.

1369
Ответ на оригинальный пост в http://forum.oberoncore.ru/viewtopic.php?p=60599#p60599

Цитата: Илья Ермаков
Цитата: Сергей Прохоренко
foreach'и бывают разными. Может быть, Вы имели дело с неудачными, и надо сделать (или позаимствовать) другой вариант? Например, с не столь безальтернативной "отначаладоконцовостью"?
Так это будет WHILE и райдер, как раз.

foreach - это райдер-итератор, спаянный намертво с циклом, при этом с циклом, который идёт от начала до конца.
Максимально специализированная вещь. Если, конечно, не разрешать "стоп-кран" break и "прыжки из поезда на ходу".

Максимально специализированная вещь - это как раз очень хорошо. Особенно, если она максимально специализирована для 90% случаев использования в конкретном проекте :)
foreach дает возможность максимально удобно обработать значения элементов последовательности. И больше ничего. Причем его основное достоинство именно в этом "ничего", а не в краткости записи :) Он не даст вам неправильно выбрать следующий элемент, он не даст вам изменить значение этого элемента, он не даст вам неправильно прописать условие завершение цикла. Он не даст вам совершить кучу ошибок. А в качестве бонуса - читающий ваш код сразу увидит, что вы не делаете здесь ничего неожиданного (см. список чего foreach "не даст") - и спокойно пойдет читать дальше более интересные вещи.

1370
Общий раздел / Re:Оберон в образовании.
« : Февраль 23, 2011, 04:52:58 pm »
Например, f(a, b, c, ^d, ^e, ^f)
Ну вот мы и вернулись к Си :-)
f(a,b,c,&d,&e,&f);
Нужны только указатели (ну, ссылками назовите, без разницы), out-параметры не нужны.

Угу. Сто лет уже не использовал указатели/ссылки для возврата значений (будучи на С++). Только для передачи модифицируемой структуры (вектор какой-нибудь) и только в "локальных" впомогательных функциях. В public интерфейсах, даже если результат - вектор, он идет в качестве нормального результата. В случаях, когда очевидно, что результат может быть очень большой и лишнее копирование недопустимо - возвращается смарт-поинтер (гарантировано ненулевой, хе-хе).

1371
Общий раздел / Re:Оберон в образовании.
« : Февраль 23, 2011, 04:43:46 pm »
В некоторых случаях мне тоже иногда видится запись типа:
(d, e, f) := f(a, b, c)

Но есть ещё VAR-параметры (и только не надо вот функционального экстремизма :) ), как их увязывать?

Экстремизма, конечно, не надо. Но вот какие-то умолчательные паттерны как "хорошо" и как "плохо" - надо. Причем синтаксис должен поддерживать наиболее удобную/короткую/понятную запись для "хороших" паттернов. Неконстантные VAR параметры - плохо, соответственно пусть везде в местах вызовов пишут "BY REFERENCE" :) Шутка, конечно, можно и "^", но тем не менее.

1372
Общий раздел / Re:Оберон в образовании.
« : Февраль 23, 2011, 03:52:56 pm »
1) Что мешает использовать OUT-параметры? Желание записать композицию нескольких функций и не вводить промежуточных переменных? Это идёт от желания (предрассудка?) быть ближе к обычной математической записи?

Математика здесь не причем. Просто более читабельная, естественная и однородная запись:
x := y;
z := f(x);

Однозначно видно откуда и куда текут данные, и кто от кого зависит. OUT параметры сразу все ломают. Почти как goto ломает поток выполнения ;)

1373
Вставлю свои 5 копеек:
1. Инициализацию модульных переменных можно делать в секции инициализации модуля - я правильно понимаю? Придумывать для этого специальный синтаксис - не обязательно.  Хотя, конечно, можно это повесить на компилятор - пусть из инициализатора сделает преобразование в секции инициализации модуля.

Я бы повесил на компилятор - инициализация модульных переменных в порядке объявления, затем вызов секции инициализации.

Цитата: Валерий Лаптев
2. Объявление по месту - мне нравится.
3. Объявление с инициализацией - ИМХО только для встроенных типов. Тем более, что это опять можно повесить на компилятор - пусть разнесет объявление и инициализацию.

Не понял. Почему только для встроенных типов и зачем разносить?

Цитата: Валерий Лаптев
Соответственно 4 - никаких конструкторов!

Да, конструкторы не нужны. Достаточно синтаксиса инициализации полей записи и элементов массива. Для массивов неизвестной длины - значение по умолчанию.

Цитата: Валерий Лаптев
Соответственно 5 - нет необходимости в механизме исключений.

Нет, механизм исключений принципиален. Если функция возвращает ненулевой указатель, то что ей вернуть, если произошла ошибка? Без исключений вся идея nullable типов и инициализации только осмысленными значениями не работает.

1374
С учётом того, что это должно быть удобным (иначе кто так будет писать?), то либо кортежи обязательны, либо структуры должны быть существенно переработаны.

С рекордами можно жить (я в С++ живу, хотя там есть boost::tuple). Писанины чуть больше, зато поля именованы, зачастую это повышает читабельность. Существенной переработки применительно к оберону не надо, достаточно иметь синтаксис для инициализации рекордов (так же как и массивов). Этот недостающий сахар уже обсуждали - без него неудобно и в классическом обероне.

Цитата: Comdiv
Я просил привести весь код, но создаётся впечатление, что многое всё же недосказано.

Ну трудно писать на гипотетическом языке, если что-то непонятно - проще пояснить словами.

Цитата: Comdiv
Что такое TypeOptional - фишка языка, позволяющая прилепливать к типу слово Optional, после чего получаем особый тип? Или он всё же где-то объявлен, тогда где его код?

Это что-то типа:
TYPE TypeOptional = OPTIONAL INTEGER;
или
typedef optional int TypeOptional;

Цитата: Comdiv
Лихо Вы объединили тернарный оператор и кортежи в один пункт,

Оно не принципиально :) Хотя тернарный оператор все же нужнее.

Цитата: Comdiv
полагаю, что 2-е намного сложнее 1-го. Также думаю, что без них нельзя, иначе фишка будет не удобной.

Чего ж там сложного??? Компилятор уже умеет иметь дело с временными переменными (для вычисления выражений). Объявление по месту - такая же временная переменная.

Цитата: Comdiv
Полагаю, что кое-что забыто (я не прогонял это тщательно в уме):
Отказ от статических структур и от структур как таковых, одни объекты, либо добавление хитрых механизмов для работы с ними.

Не, не понял. Что такое статические структуры?

Цитата: Comdiv
Добавление конструкторов, да не простых, а с инициализацией всех данных объекта.

Не. Можно без конструкторов. Просто синтаксис для инициализации рекордов. Если полей много - делается обычная вспомогательная функция-конструктор. Ничего в язык добавлять не надо.

Цитата: Comdiv
Объявление данных модуля с инициализацией.
Отказ от данных модуля, которые  не могут быть инициализированы по месту.

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

Цитата: Comdiv
Как-то придумать инциализацию по месту массивов, или отказ от них.

Да, да. Давно пора нормально инициализировать массивы :) Если массив большой - да, есть проблема в дополнительных накладных расходах. Но мне не кажется, что это что-то принципиальное. Ну зачем может быть нужен неинициализированный большой массив? Жуткую матрицу посчитать? Так оно считать будет много дольше, чем инициализировать.

Цитата: Comdiv
Отказ от 1-го RETURN (Оберон ведь движется в этом направлении)

А может это неправильное направление? :)

Цитата: Comdiv
Возможно, что-то ещё.

Про исключения не понял, почему нельзя возвращать код ошибки вместе с результатом?

Потому что результат будет "мусорным" в случае ошибки. А мы не хотим мусорных значений.

Цитата: Comdiv
По-моему вырисовывается не диалект Оберона, а совсем другой язык.

Да ладно. До какого-нибудь С++ или жабы такому диалекту очень далеко :) А определенные проблемы решаются.

Цитата: Comdiv
Предложу свои варианты ответов:
1.При необходимости многие будут не выкручиваться в эквивалентные преобразование кода, а инициализировать по месту мусорно, что затруднит обнаружение ошибки, в случае если переменная так и не будет проинициализирована нормально (за что боролись, на то и напоролись).

Да вы никогда не заставите писать правильно. Но вот если писать правильно будет проще, чем неправильно, то среди неправильных программистов с накоплением опыта будет определенная миграция в правильную сторону. Например, проинитить указатель нулем уже не получится. Придется писать OPTIONAL, а потом явно приводить такой указатель к ненулевому. Глядишь, подумают чуть-чуть, и сделают так, что указатель сразу будет инициализирован чем-то осмысленным.

Цитата: Comdiv
2.Усложнение языка и компилятора, ради небольшой проблемы. Ведь изначально шла речь о простом изменении, существенно более простом, чем то, что реализовано в анализаторе BlackBox или компиляторе java. А если нам нужен другой язык, с кортежами, исключениями, nullable типами и другими фишками, это другой вопрос.

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

Цитата: Comdiv
3.Возможно, что-то ещё. Мне не так-то просто предвидеть все последствия от необходимых изменений.

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

1375
Общий раздел / Re:Парадокс Блаба.
« : Февраль 21, 2011, 03:11:43 pm »
Пардон, в статье про Хаскел ни слова. Более того, Грейхем считает, что он хуже Лиспа.
Поэтому я предлагаю обсудить (и попытаться опровергнуть) тезис:
"Любой макрос демонстрирует дефект в языке или в голове программиста".

Я его привожу по памяти, если кто-нибудь найдет первоисточник, буду очень благодарен.

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

1376
Напишите, пожалуйста, весь код.

C расчетом, что у нас в языке а-ля оберон с сишным синтаксисом есть туплы (если нет, то всегда можно отбиться структурами/записями):
(Type t1, TypeOptional t2)
f() {
    if (c1) {
        Type t3 = f0(p1, p2);    
         return f1(p1, t3), f2(p2, t3);
    } else {
        return t1, null;
    }
}
...

Type t1, TypeOptional t2 = f();
...
if (optional_cast<Type>(t2) && c2) {
   f5(t1);
   f6(t2); // здесь t2 гарантировано не "пустое", компилятор про это знает, потому что выше произошла проверка/приведение типа от TypeOptional к Type
} else {
   f7(t1);
}

Цитата: Comdiv
А заодно опишите, какими свойствами должен обладать язык, чтобы делать такие штуки было удобно. И как Вы считаете, можно ли считать это правило маленькой добавкой в язык уровня Оберон (когда-то Вы писали, что оно легко и элегантно впишется в его гипотетический диалект).

Если в порядке "величины" добавки, то от языка нужны следующие свойства:
1. Механизм исключений в каком-то виде. Если инициализировать при объявлении, то код ошибки обрабатывать уже негде. Да, это совсем немаленькая добавка, но зато хорошо изученная и без нее жить трудно безотносительно к предлагаемым изменениям.
2. Объявление локальных переменных по месту (упразднение отдельной секции VAR). Тоже повсеместно доказанное благо, хотя убежденные паскалисты держатся за нее до конца :)
3. Добавление null'able в систему типов. Существующих примеров много, начиная с SQL и заканчивая C#, ничего нового, все известно и понятно.
4. Тернарный оператор и туплы. Можно и без них (особенно без туплов), но с ними приятнее :)

Цитата: Comdiv
Также подумайте, чего этот способ делает больше: решения проблем или их создания (просто подумайте, отвечать не надо, поскольку Ваш ответ и так очевиден с вероятностью 87.34%).

Я пока не нашел каких-то проблем/противоречий, к которым могут привести предлагаемые изменения. Изменений в компиляторе относительно немного. Язык станет более выразительным (за счет расширения системы типов) и сменится стиль написания кода в сторону более гранулярной декомпозиции (как в данном примере).

1377
Общий раздел / Re:ASSERT
« : Февраль 21, 2011, 02:27:07 pm »
Ну вот смотрите, предположим у вас кусок сложных вычислений. Утверждений ASSERT(x >y) рядом штук 10. От все вышеперечисленно будет мало толку. Нужна строка с объяснением логики. Вполне возможно, что в терминах более высокого уровня, чем x и y.

У нас, кстати, есть неотключаемая версия ассерта с вторым параметром в виде строки. И у меня постоянно возникают проблемы с придумыванием этой самой строки. Приходится вбивать что-то на отвяжись. Все равно будет непонятно, пока не полезешь в код и не посмотришь. А чтобы полезть и посмотреть достаточно имени исходника и номера строки. А еще лучше - полноценный дамп стэка.

P.S. Да, если таки у сложного ассерта есть простое объяснение, то оно просто записывается в виде комментария напротив этого ассерта.

1378
Общий раздел / Re:ASSERT
« : Февраль 21, 2011, 02:20:10 pm »
Не помню, как предписано стандартом языка, но по факту в BB ассерты проверяются не только в run-time, но даже уже на этапе компиляции. Поэтому ASSERT(FALSE) воспринимается компилятором как семантическая ошибка. Когда я это обнаружил, то был немного удивлён. Для безусловного останова вместо такого ассерта предлагается использовать HALT. В этом случае ошибки не возникает, и компиляция пройдёт успешно.

Да, интересно, зачем на практике такое свойство можно использовать? И как далеко компилятор идет в своем рвении? Любое выражение с константами, дающее FALSE? Или жестко FALSE как лексема?

Цитата: igor
А, так Вы не знали, что ASSERT можно использовать без второго параметра?  :o

Да, не знал, в ББ'шных исходниках второй параметр всегда присутствует.

1379
Общий раздел / Re:ASSERT
« : Февраль 21, 2011, 02:16:30 pm »
Если ASSERT сработал на машине пользователя, то среда должна сформировать слепок состояния программы, дамп памяти, в виде пригодном для последующего анализа.
Стоп. А где в стандарте языка сказано, что среда должна всё это сделать?  ;)

Вообще в стандарте, который репорт, мало чего сказано (а то в 16 страниц было бы не уложиться). Много чего отдано на откуп здравому смыслу. По факту, найти сейчас современную реализацию ЯП, которая не позволяла бы диагностировать фатальные проблемы в виде стэка/дампа - очень сложно. Для экстремальных случаев, типа выдать рабочий компилятор/рантайм для экзотической железки за человеко-месяц - да, можно сэкономить и использовать второй параметр в ассерте.

1380
Общий раздел / Re:ASSERT
« : Февраль 20, 2011, 03:16:54 am »
Нет, я что-то не совсем понимаю зачем это самое целочисленное значение ассерту скармливать.

Я тут полазил по сообщениям о языках, вот что я нарыл:
оригинальный оберон от Вирта: ASSERT отсутствует, есть HALT
оберон-07: ASSERT есть в двух перегруженных видах - с и без числа.
ББ: ASSERT тоже двух видов, HALT присутствует. Разница между ASSERT(FALSE, n) и HALT(n) не поясняется. HALT очень смахивает на лишнюю сущность ;)

Сделаю предположение, что ASSERT с вторым параметром Вирт оставил для случая, когда компилятор делается настолько простым, что не в состоянии вкомпилить номер строки и имя модуля. О нормальном стэктрэйсе в таком случае тоже говорить не приходится. А отлаживаться как-то надо.

P.S. На форуме мало истинных оберонщиков. Они бы сразу ткнули в ASSERT без второго параметра.


Страницы: 1 ... 90 91 [92] 93