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

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Возвращаясь к нашим баранам. Зачем иметь локальные переменные в отдельной декларативной части? Есть какие-нибудь формальные причины, кроме "здесь так заведено"?
В первую очередь это самое простое из достаточных решений, вдобавок, близкое к генерируемому коду.
Стимулирует писать обозримые процедуры. Кстати, встроенные процедуры смазывают это, но нужны по другой причине.
Простое средство от дополнительных ошибок, связанных с перекрытием.

int i = 0;
func() {
a = i;
{
int i = 1;
b = i;
}
}

или ещё хуже

int i = 0;
func() {
a = i;
int i = 1;
b = i;
}
Подобные вещи дают сбои редко, но метко, как правило, при длительном развитии кода, особенно несколькими людьми.
Дополнительное веселье может начаться, если в языке есть перегрузка функций, тогда может не спасти и типизация при разнотиповом перекрытии.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
В первую очередь это самое простое из достаточных решений,

Отдельная секция - самое "просто" решение? Издеваешься? Самое простое - это как в питоне:
def func():
    i = 0

Проще не могу придумать.

вдобавок, близкое к генерируемому коду.

Не понимаю о чем ты... Вот мне надо генерировать жабаскрипт... ;)

Стимулирует писать обозримые процедуры.

Ой неправда. Достаточно глянуть код самого Мэтра. Зато вот дублирование названия процедуры в конце - да, очень понятно. Как раз на случай необозримых процедур.

Простое средство от дополнительных ошибок, связанных с перекрытием.

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

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Самое простое - это как в питоне
А как в питоне?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Самое простое - это как в питоне
А как в питоне?

Я ж привел код:
def func():
    i = 0

Функция func и ее локальная переменная i. Если месье любит глобальные переменные - пусть страдает и пишет вот так:
i = 0

def func():
    global i
    i = 1

Т.е., явно декларирует, что хочет импортировать в локальную область глобальную переменную. А по умолчанию - все локально. И с минимумом усилий для нормальных людей, которые не любят глобальные переменные. И это правильно.

Илья Ермаков

  • Sr. Member
  • ****
  • Сообщений: 493
    • Просмотр профиля
Это в смысле так же, как в PHP?
Сочетание директивы global с автоматическим созданием переменной при упоминании?
При котором редко пишуший на языке человек может потратить час на то, чтобы понять, почему это не работает?
Идея явно указывать global неплоха, но становится ужасной, если для локальных нет явного объявления, что переменная создаётся впервые.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Это в смысле так же, как в PHP?

Не знаю - повезло, не писал :)

Сочетание директивы global с автоматическим созданием переменной при упоминании?
При котором редко пишуший на языке человек может потратить час на то, чтобы понять, почему это не работает?
Идея явно указывать global неплоха, но становится ужасной, если для локальных нет явного объявления, что переменная создаётся впервые.

Да, кажется страшным. И в большинстве языков хоть что-то есть для обозначения декларации новой переменной (var, let). Но на практике - не сталкивался ни с какими проблемами. Довольно много приходится с питоном иметь дело - вот именно с этим проблем никогда не было. Возможно, как я уже говорил, зависит от стиля пишущего. Я практически не использую глобальные  переменные, и у меня нет привычки менять переменные из внешнего скопа во внутреннем (тоже моветон само по себе). Так что все хорошо, проверено лично :)

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
и у меня нет привычки менять переменные из внешнего скопа во внутреннем (тоже моветон само по себе)
Не понял. Какая тогда польза от внутреннего скопа? Или речь опять про функциональные языки?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
и у меня нет привычки менять переменные из внешнего скопа во внутреннем (тоже моветон само по себе)
Не понял. Какая тогда польза от внутреннего скопа? Или речь опять про функциональные языки?

Не понял. Зачем менять внешнее состояние во внутреннем скопе? Внутренний скоп получил данные, обработал (при этом завел кучу локальных переменных, если надо) и вернул результат. Вход -> выход. Просто и понятно. Конечно удобно иметь внешний "контекст", чтоб не таскать все через аргументы (вход). Поэтому идем на уступку - внешний скоп виден внутреннему. Но вот так вот брать и откровенно гадить во внешнем скопе брутальными присваиваниями - не, этого нам не надо.  Возвращаясь к питоновскому примеру:
i = 0

def func():
    global i
    i = 1

Вот это откровенно хреновый код. И тот, кто такое пишет, должен страдать. По-нормальному должно быть переписано вот так:
i = 0

def func():
    return 1

i = func()

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Кажется понял. Для тебя глобальный скоп и внешний одно и то же?

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Кажется понял. Для тебя глобальный скоп и внешний одно и то же?

Разница между областями видимости, глобальной для всех процедур, и внешней для конкретной процедуры, -- непринципиальна...
to iterate is human, to recurse, divine

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

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Под внешним я подразумевал только 1 родительский уровень:
var a
scope1:{
var a1
scope2:{
var a2
scope3:{
var a3
}
}
}

Для scope3 это одна переменная a2

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Отдельная секция - самое "просто" решение? Издеваешься? Самое простое - это как в питоне:
def func():
    i = 0
У динамических языков своя логика, с моей точки зрения не самая лучшая. Я имел ввиду самое простое для реализации компилятора из достаточно хороших для пользователей языка. Для статически типизированного императивного языка то, что в Питоне ни достаточно хорошо, ни достаточно просто.

Цитата: vlad
вдобавок, близкое к генерируемому коду.
Не понимаю о чем ты... Вот мне надо генерировать жабаскрипт... ;)
естественно, речь о применении Оберона по назначению

Цитата: vlad
Стимулирует писать обозримые процедуры.
Ой неправда. Достаточно глянуть код самого Мэтра. Зато вот дублирование названия процедуры в конце - да, очень понятно. Как раз на случай необозримых процедур.
Правда. Стимулирует - не значит обязует, и то - хлеб. Дублирование названия в конце при сколь-нибудь вменяемом форматировании не несет существенной пользы для обзора необъятной процедуры. А вот простому парсеру языка восстановиться после ошибки в коде, особенно при наличии встроенных процедур в языке, помогает.

Цитата: vlad
Простое средство от дополнительных ошибок, связанных с перекрытием.
Перекрытие и отдельная секция VAR совершенно отртогональные вещи. Твой сишный пример замечательно переписывается на обероне с помощью локальных процедцур. И с теми же потенциальными проблемами. Про которые Вирт, кстати, в репорте молчит. Видимо не счиатает важным. Т.е., про область видимости он упоминает, а вот про то как разрешаются конфликты в случае перекрытия - молчит.
Не ортогональные. Не переписываются примеры на аналогичные с локальными процедурами, а главное в примере и нет никаких локальных процедур. В первую очередь с отдельной секцией очевидно, что если какая-то переменная в ней есть - она именно локальна, и не надо выискивать, есть ли где в мешанине коде объявление/перекрытие

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Под внешним я подразумевал только 1 родительский уровень:
var a
scope1:{
var a1
scope2:{
var a2
scope3:{
var a3
}
}
}

Для scope3 это одна переменная a2

Но ведь в scope3 доступны также и a1, и даже a. Так какая разница?
to iterate is human, to recurse, divine

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

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Вопрос не в том что доступно, а в том, что можно изменять в каждом скопе.
Проблемы с изменением глобального скопа известны и понятны. Но проблемы ведь не в том, что внутренний скоп изменяет переменные внешнего.

Вложенные процедуры, замыкания, локальные переменные в циклах (да и любые локальные переменные в блоках). Все это имеет смысл только при изменении переменных внешнего скопа.


ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Пример кода:
a = 1
b = 2
do -- обмен переменных значениями
    local temp
    temp = a
    a = b
    b = temp
end

Какие тут могут быть проблемы?