Автор Тема: локальные переменные в отдельной декларативной части  (Прочитано 43244 раз)

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
http://www.inf.ethz.ch/personal/wirth/ProjectOberon/Sources/Checkers.Mod.txt
Обрати внимание на то где объявляется переменная цикла, а где сам цикл. Зачем???
Не вижу никакого криминала. Вот если бы переменная i экспортировалась для чтения и записи, тогда да. А так, это внутренние дела суверенного модуля в центре Европы:) (начитался новостей  :) )

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
По сравнению с обероновским всё по полочкам, это будет мешанина даже в 10 строках.
Вот, кстати, хорошая иллюстрация (обсуждалась в курилке): http://www.inf.ethz.ch/personal/wirth/ProjectOberon/Sources/Checkers.Mod.txt
Обрати внимание на то где объявляется переменная цикла, а где сам цикл. Зачем???
Откуда мне знать? Там, очевидно, напрашивается процедура с кодом инициализации, в которой эта переменная и должна быть объявлена. Видимо автор решил, что для такого модуля можно не заморачиваться.

Вот такой код без лишних заморочек и является говнокодищем...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
vlad, это глобальная переменная.

Дык!!! Именно эту проблему я и пытаюсь тут донести - формально глобальная переменная, а по факту использования - локальная переменная цикла. Вот такое вот несоответствие декларации и фактического использования на простом программерском языке называется "говнокод".

Очевидно, что она будет использоваться далеко от объявления. VAR тут совершенно не виноват.

Э... в смысле не виноват? А кто тогда виноват?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
А причем тут глобальность - переменная используется в секции инициализации(телу) модуля, для которой данная переменная локальна. Единственное, что можно было бы сделать - как в старших Оберонах - произвольное расположение секций, тогда секцию VAR с этой переменной можно было бы прижать к телу модуля

Это не единственное, что можно сделать :) Можно набраться критического мышления и смелости и сказать, что секция VAR вообще ненужна, а локальные переменные объявлять по мере надобности, максимально ограничивая их область видимости.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Но разве это аргумент против VAR?

Я даже и не знаю как прокомментировать... "GOTO легко приводит к говнокоду - но разве это аргумент против GOTO?"

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Пример несколько надуман. Однако тип можно оставить, почему нет. Отдельная секция для этого все равно не нужна:
Цитата: vlad
i: int = 123
Для кого надуман, для кого - бытовуха.

Гы. На каком языке ты писал и вляпался (неоднократно, раз это бытовуха) вот в такое?

Однажды проходя мимо коллеги, внезапно увидел знакомые "BEGIN - END". Когда я спросил его, что это, он ответил, что VHDL, а ключевые слова хоть и не регистрозависимые, но заглавными буквами ему удобней. Я посмеялся, вспомнив широко известную в узких кругах спецолимпиаду. Человеку 24 года, об Обероне не слышал, программирует на Си.

Ну и что? Я на SQL тоже пишу капсом ключевые слова. Потому что пишу их в фаре без подсветки. Это говорит лишь о том, что у человека нет нормального инструмента. Например, в силу относительной ненужности (как мне - раз в месяц написать несколько строк на SQL).
Вот когда человек, имея язык без VAR и без  паскального прошлого, начнет переменные лепить в одну кучку - тогда это будет интересно. Я, возможно, даже соглашусь списать это на устройство мозгов конкретного индивидуума.

Цитата: vlad
Сформулируй, что является достаточным.
Единое поле видимости для всей функции, очевидность принадлежности, логичность представления. Увы, кроме 1-го, всё достаточно субъективно, особенно 3-й, так что попытки найти идеальный общий знаменатель будут бесплодны.

Да, это печально.

Цитата: vlad
Хорошо, у тебя есть сведения, что виртовский (или какой-то другой) компилятор использует эту особенность для восстановления после ошибок? Или это все-таки было придумано по ходу дела?
Как минимум тот, что пишу я(свет скорей всего не увидит)

Так. Понятно. ТруЪ оберонщик детектед. Опять какие-то секретные репозитории и разработки... Можно хотя бы в общих словах - что за компилятор (как компиляторостроитель компиляторостроителю)?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Там, очевидно, напрашивается процедура с кодом инициализации, в которой эта переменная и должна быть объявлена. Видимо автор решил, что для такого модуля можно не заморачиваться.

Именно. Да, можно сделать код лучше и имея VAR, но этого не делается. Потому что вступает в силу мой любимый тезис: "на любом языке пишут так, как короче, а не как правильнее". Поэтому мне и непонятно вот это стремление сохранить VAR любой ценой только потому, что и с ним можно писать хороший код. Трудно, но ведь можно...

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Вот такой код без лишних заморочек и является говнокодищем...

Да, там в одном этом маленьком файле можно наковырять несколько плохих штук... Переменная checks - ничем не лучше. Волшебные циферки - 9, 17...

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Но разве это аргумент против VAR?
Я даже и не знаю как прокомментировать... "GOTO легко приводит к говнокоду - но разве это аргумент против GOTO?"

Легко ты аргументами манипулируешь.
Как раз отсутствие VAR легко приводит к говнокоду, т.к. место объявления переменной ни чем не ограничено. VAR - это ограничение. Также как отсутствие GOTO - это ограничение.
В обероне переменная объявляется в начале скопа. Есть всего три уровня скопов:
1. Модуль
2. Процедура
3. Вложенная процедура

С какого перепуга скоп должен делиться на две части этими произвольными объявлениями?

scope:
int a;
// до сих в скопе одна переменная a
int b;
// а тут еще b добавилась
end;

Такие скопы даром не сдались.

Если ты хочешь иметь произвольные вложенные скопы (по твоим сообщениям складывается такое впечатление), то к VAR это уже не имеет отношения.

scope1:
  int a;
  scope2:
    int b;
  end;
end;

Так ты произвольные объявления хочешь или скопы?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Как раз отсутствие VAR легко приводит к говнокоду, т.к. место объявления переменной ни чем не ограничено.

Ты сам согласился, что виртовский код с отделением переменной цикла от цикла некошерен. Не? Я всего лишь предлагаю простое решение этой проблемы. Причем не добавлением новых фич в язык , а переосмыслением старой - выкинуть VAR в существующем виде и  добавить объявление переменных "по месту".

С какого перепуга скоп должен делиться на две части этими произвольными объявлениями?

Скоп не делится. Он уточняется по ходу дела. В чем проблема-то? Ну хоть один аргумент против, кроме абстрактных "усложнений компилятора" и "мешанина в коде"? Можно пример мешанины, но такой, что ее нельзя переписать в более короткий и понятный код (без секции VAR). Потому как примеров, когда секция VAR только мешает - вагон, включая код Вирта с переменной цикла в глобальном скопе.

Так ты произвольные объявления хочешь или скопы?

Во-первых, произвольные объявления. После чего операторные скопы (циклы, IF'ы) возникают как естественное дополнение.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Скоп не делится. Он уточняется по ходу дела.

Замечу, что это прямая аналогия существующего порядка объявления процедур. Ты не можешь использовать в коде процедуры еще не объявленную процедуру. И никто по этому поводу не бегает и не кричит - как же так, скоп делится. И никто не заставляет объявить все процедуры заранее в отдельной секции PROCEDURES...

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Скоп не делится. Он уточняется по ходу дела.

Замечу, что это прямая аналогия существующего порядка объявления процедур. Ты не можешь использовать в коде процедуры еще не объявленную процедуру. И никто по этому поводу не бегает и не кричит - как же так, скоп делится. И никто не заставляет объявить все процедуры заранее в отдельной секции PROCEDURES...
Более того, такую возможность Вирт специально выпилил убрав forward declarations в Обероне для процедур.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Вообще многие штуки в Обероне не следует воспринимать как некие вечные ценности, и как нечто за чем стоит Великий Замысел. Там очень много ситуационного, которое логично и понятно становится в контексте конкретно Оберон-ОС и Оберон-компа. Ну, например в этом контексте становится очевидным почему Вирт выпилил из Оберона массивы с длиной неизвестной на этапе компиляции. Абсолютно логичный ход вообще то :-)
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
В общем vlad смотри: https://github.com/id-Software/DOOM-3-BFG/blob/master/neo/framework/CmdSystem.cpp
Православные сишники внезапно объявляют переменные всегда (за редким исключением) в начале блока. Вот же парадокс! И с чего это им вздумалось VAR эмулировать?

Цитировать
Ты сам согласился, что виртовский код с отделением переменной цикла от цикла некошерен. Не?
В одном единственном случае. Конкретно в цикле FOR считаю что переменная не должна объявляться вообще. Т.е. это узкое частное решение не делающее ничего кроме очистки VAR от мусора. А ты говоришь о совершенно других вещах.


valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
В общем vlad смотри: https://github.com/id-Software/DOOM-3-BFG/blob/master/neo/framework/CmdSystem.cpp
Православные сишники внезапно объявляют переменные всегда (за редким исключением) в начале блока. Вот же парадокс! И с чего это им вздумалось VAR эмулировать?
Это очень олдовые сишники, пришибленные еще С89, в котором по другму было и нельзя. На С++ перешли с С89, но привычка осталась. При этом С++ там используется чисто как Си89 с классами. (видно по переменным типа commandDef_t *cmd, **prev;)

Можно взять пример посовременней:
https://github.com/llvm-mirror/clang/blob/master/examples/clang-interpreter/main.cpp
https://github.com/llvm-mirror/clang/blob/master/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
Y = λf.(λx.f (x x)) (λx.f (x x))