Re[11]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 00:02
Оценка:
ВВ>Ты путаешь разные вещи. Объявление и присвоение. Присвоение, ес-но, динамическое и не будет сделано, пока поток исполнения не дойдет до этой инструкции. Это во всех языках так.
ВВ>Присвоение не статическое, но объявление статическое. Сравни:

Да, там смысл не в присвоении, я неправильно сказал, код работает. Он принтит undefined.

Значит в жаваскрипте две статические конструкции: function и var. Спасибо за ликбез.

ВВ>Речь об обязательности декларации с опциональным определением:


var x; то есть.
Да, иногда, очень редко, такое полезно. Но было бы лучше, если б язык предоставлял более изящные средства для решения задач, в которых сейчас применяется декларация без определения.

T>>И опять же, я не думаю, что у всех динамических языков серьёзно есть какая-то общая идеология на тему декларации переменных. Межгаллактический совет разработчиков динамических языков нужен тут.

ВВ>Тем не менее есть определенная практика и какие-то вещи могут быть удобными/неудобными, хорошо вписывающимися в дизайн или нет. Я об этом и спрашиваю. А не о том, соответствует ли сие закону о динамических языках от джедайского совета.

Посыл в том, что у каждого языка свой дизайн.

T>>То есть без ключевого слова это уже неявное определение? Тогда в Python/Ruby/Erlang все определения неявные?

ВВ>Именно так. Все правильно.

Хакей. Ну так вот неявность определений... как бы это... нормальна. Она не создаёт неудобств сама по себе.

ВВ>Ну в таком случае возможность объявлять глобальные переменные из функций должна быть признана еще большим злом.


Ещё большим, так ещё большим. Согласен.
Но когда это ограничение обходится вот так:

state = {}
def f():
if condition:
state['field'] = 1
else:
state['field'] = 2

то получается, что зло просто переименовано в зло+гемор.

T>>Короче вы хотите сделать как в Python/Ruby, но с ключевым словом. Если это в жаваскрипт, то предложение отличное, потому что решает существующую проблему "что имел в виду автор кода x = 2 в неглобальном скопе". Если это в какой-то новый язык, то на мой взгляд ключевое слово лишнее, т.к. вы можете убрать неоднозначность другими способами.

ВВ>С неоднозначностью проблем нет. Для введения ключевого слова есть 2 причины, указанные ранее. Других причин нет. Основная в принципе первая. Очень уж вкусная оптимизация получается.

На первый взгляд оптимизация одинаково возможна с ключевым словом и без. Может быть я не вижу всей картины.
Re[11]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 00:10
Оценка:
T>>Если говорить о красивости решений, то меня очень напрягает возможность переопределять глобальные переменные из функций. Вообще, неявный доступ на запись к глобальным переменным (например, global_obj.attr = 2) это зло, потому что ведёт к трудноуловимым ошибкам.

ВВ>Вообще мне кажется, это есть следствие того, как реализованы замыкания в ДжаваСкрипте. Замыкание захватывает весь контекст родительского скопа, независимо от того, какие переменные там реально используются, и по сути обращения к этим переменным и происходят как к переменным родительского скопа. Потому они и сделаны неявными.

ВВ>По замыканиям прекрасно видно, что их собственный "блок" памяти живет только время вызова, а замкнутый блок статичен:

ВВ>
ВВ>var f = Foo();
ВВ>f();
ВВ>f();

ВВ>function Foo()
ВВ>{
ВВ>    var x = 0;
ВВ>    return function() 
ВВ>    { 
ВВ>        var y = 0;
ВВ>        alert(++x + ";" + ++y); 
ВВ>    }
ВВ>}
ВВ>


ВВ>В результате двух вызовов имеем:


ВВ>1;1

ВВ>2;1

Вроде всё понятно, что вы говорите, но результат примера для меня совершенно нормальный и ожидаемый. Foo() создало переменную и функцию и замкнуло функцию на эту переменную. Потом функция модифицирует переменную и результат этого изменения виден. Это и называется замыкание.

Вы хотели бы, чтоб оно работало иначе или что?
Re[12]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 00:34
Оценка:
Здравствуйте, Temoto, Вы писали:

T>>>И опять же, я не думаю, что у всех динамических языков серьёзно есть какая-то общая идеология на тему декларации переменных. Межгаллактический совет разработчиков динамических языков нужен тут.

ВВ>>Тем не менее есть определенная практика и какие-то вещи могут быть удобными/неудобными, хорошо вписывающимися в дизайн или нет. Я об этом и спрашиваю. А не о том, соответствует ли сие закону о динамических языках от джедайского совета.
T>Посыл в том, что у каждого языка свой дизайн.

Хорошо. Примеры, почему var вписывается или не вписывается в какой-то конкретный дизайн меня вполне устроят.

T>>>То есть без ключевого слова это уже неявное определение? Тогда в Python/Ruby/Erlang все определения неявные?

ВВ>>Именно так. Все правильно.
T>Хакей. Ну так вот неявность определений... как бы это... нормальна. Она не создаёт неудобств сама по себе.

Я и не утверждал обратного.

ВВ>>С неоднозначностью проблем нет. Для введения ключевого слова есть 2 причины, указанные ранее. Других причин нет. Основная в принципе первая. Очень уж вкусная оптимизация получается.

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

Ключевое слово — статическое. Остальные объявления — нет. Поэтому и неизвестно, "задействовано" какое-то имя или нет, в каком оно скопе и так далее. Может быть, оптимизация и возможна, но ценой слишком уж дорогих для интерпретируемого языка эвристик. Скоп-то все же не до конца динамический и имеет свои лексические ограничения. А при наличии замыканий, учитывая, что внутри замыкания может быть другое замыкание, внутри которого... и так далее — все становится еще веселее.
Представь вот, как определить не в рантайме, что за переменная используется внутри замыкания — своего собственного скопа или "захваченного".
Re[12]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 00:37
Оценка:
Здравствуйте, Temoto, Вы писали:

T>Вроде всё понятно, что вы говорите, но результат примера для меня совершенно нормальный и ожидаемый. Foo() создало переменную и функцию и замкнуло функцию на эту переменную. Потом функция модифицирует переменную и результат этого изменения виден. Это и называется замыкание.

T>Вы хотели бы, чтоб оно работало иначе или что?

Не, не, не, все работает как нужно. Но ведь по факту внутри замыкания мы и имеем то, что называешь злом — изменение переменной, которая не принадлежит ее контексту. При этом любая функция по сути является замыканием, независимо от того, в какой форме она объявлена. Отсюда ИМХО и такой эффект.
Т.е. если этот код тебе кажется совершенно нормальным, почему тебя смущает:

var x = 0;

function Foo() {
  x++;
}


Ведь это тоже самое. Просто Foo в данном случае замкнута на глобальный контекст.
Re[13]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 01:01
Оценка:
ВВ>Не, не, не, все работает как нужно. Но ведь по факту внутри замыкания мы и имеем то, что называешь злом — изменение переменной, которая не принадлежит ее контексту. При этом любая функция по сути является замыканием, независимо от того, в какой форме она объявлена. Отсюда ИМХО и такой эффект.
ВВ>Т.е. если этот код тебе кажется совершенно нормальным, почему тебя смущает:

ВВ>Ведь это тоже самое. Просто Foo в данном случае замкнута на глобальный контекст.


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

Вообще я за имутабельность и стараюсь писать код соответственно (то есть в реальной жизни я не напишу нелокальный x++ без веской причины), но тут речь про скопы. Различаю сорта скопов.
Re[13]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 01:13
Оценка:
T>>Посыл в том, что у каждого языка свой дизайн.

ВВ>Хорошо. Примеры, почему var вписывается или не вписывается в какой-то конкретный дизайн меня вполне устроят.


У меня предвзятый взгляд в сторону того, что var лишний, поэтому примеры будут такие:

В Python, Ruby var не вписывается, потому что в этих языках синтаксический гемор стремится (но ещё не достигает ) к минимуму.
В Erlang по гемору var вписывается, но там есть довольно мощный паттерн-матчинг и я не уверен, что подобное смотрелось бы нормально: {ok, var IsLiquid, [var First|var Rest]} = func().

ВВ>>>С неоднозначностью проблем нет. Для введения ключевого слова есть 2 причины, указанные ранее. Других причин нет. Основная в принципе первая. Очень уж вкусная оптимизация получается.

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

ВВ>Ключевое слово — статическое. Остальные объявления — нет. Поэтому и неизвестно, "задействовано" какое-то имя или нет, в каком оно скопе и так далее. Может быть, оптимизация и возможна, но ценой слишком уж дорогих для интерпретируемого языка эвристик. Скоп-то все же не до конца динамический и имеет свои лексические ограничения. А при наличии замыканий, учитывая, что внутри замыкания может быть другое замыкание, внутри которого... и так далее — все становится еще веселее.

ВВ>Представь вот, как определить не в рантайме, что за переменная используется внутри замыкания — своего собственного скопа или "захваченного".

И символ '=' статический.
У нас же есть дерево исходника. В нём можно найти все foo = expr. И узнать самое верхнее (по дереву) определение для каждого имени. Оно и будет декларацией. Или я что-то упустил?
Вы ошибку неупотребления var при компиляции искать будете? Это та же самая задача.
Re: Динамические языки и переменные
От: c-smile Канада http://terrainformatica.com
Дата: 06.03.10 01:36
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Возьмем всем известный ДжаваСкрипт. Там объявление переменной без var считается моветоном, хотя бы потому что его семантика кардинально отличается от объявления с var (однако по коду это совершенно неочевидно):


ВВ>
ВВ>function Foo()
ВВ>{
ВВ>  var x = 1; //переменная в скопе Foo
ВВ>  y = 2; //А вот уже переменная в глобальном скопе
ВВ>}
ВВ>


Кстати в javascript как и в питоне есть такая грустная фенечка:

function Foo()
{
  var x = 1; 
  y = 2;     // y is a local variable here.
  if( x == 0 )
  {
    var y;   // because of this
  }
}


А вообще это конечно зло. Неявное образование переменных я имею ввиду.

Вот такая конструкция делает то что надо и явным образом.

var y = 1;
function Foo()
{
  var x = 1; 
  y = 2;     // y is a local variable here.
}


Тяжелое наследие Basic?
Re[14]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 01:47
Оценка:
Здравствуйте, Temoto, Вы писали:

T>И символ '=' статический.

T>У нас же есть дерево исходника. В нём можно найти все foo = expr. И узнать самое верхнее (по дереву) определение для каждого имени. Оно и будет декларацией. Или я что-то упустил?

"=" может быть как декларацией, так и изменением существующего значения. Представь себе тело некоего замыкания вида { x = 2 }. Здесь что происходит? Изменение захваченной переменной? Объявление новой?

T>Вы ошибку неупотребления var при компиляции искать будете?


Нет, конечно.
Re[2]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 01:52
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Кстати в javascript как и в питоне есть такая грустная фенечка:


CS>
CS>function Foo()
CS>{
CS>  var x = 1; 
CS>  y = 2;     // y is a local variable here.
CS>  if( x == 0 )
CS>  {
CS>    var y;   // because of this
CS>  }
CS>}
CS>


Мы тут подобное обсуждали. В принципе поведение вполне ожидаемое для динамического скопа, с учетом того, что объявление переменной вида "var y" по сути скорее инструкция для компилятора (добавить имя y в карту переменных), чем некий исполняемый код. Потому и по фиг в принципе, где она находится.

А у тебя как?

CS>А вообще это конечно зло. Неявное образование переменных я имею ввиду.


CS>Вот такая конструкция делает то что надо и явным образом.

CS>
CS>var y = 1;
CS>function Foo()
CS>{
CS>  var x = 1; 
CS>  y = 2;     // y is a local variable here.
CS>}
CS>

CS>Тяжелое наследие Basic?

Что именно? Неявное объявление? Ну с т.з. динамических языков вроде как вполне логично. Переменная как имя для некоторого значения. Зачем ее еще объявлять. Дал имя значению — и все тут.
Т.е. ты считаешь, что объявления всегда стоит сделать явными? В TiScript это так?
Re: Динамические языки и переменные
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.03.10 02:07
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Если эту возможность убрать (т.е. в примере выше была бы ошибка) потеряет ли язык в выразительности?


Нет. Он станет только надежнее и понятнее, т.е. выиграет во всех аспектах.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 02:24
Оценка:
T>>И символ '=' статический.
T>>У нас же есть дерево исходника. В нём можно найти все foo = expr. И узнать самое верхнее (по дереву) определение для каждого имени. Оно и будет декларацией. Или я что-то упустил?

ВВ>"=" может быть как декларацией, так и изменением существующего значения. Представь себе тело некоего замыкания вида { x = 2 }. Здесь что происходит? Изменение захваченной переменной? Объявление новой?


Во-первых, вы проигнорировали "самое верхнее по дереву" или в данном случае это не поможет, а я не уследил почему именно?
Во-вторых, эту неоднозначность можно убрать семантически (о чём мы уже говорили выше). Например, можно (как в петоне) ввести правило: '=' всегда определяет имя в текущем скопе. В таком случае, кажется, дерево точно поможет найти объявление (первое определение).
Re[16]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 02:33
Оценка:
Здравствуйте, Temoto, Вы писали:

ВВ>>"=" может быть как декларацией, так и изменением существующего значения. Представь себе тело некоего замыкания вида { x = 2 }. Здесь что происходит? Изменение захваченной переменной? Объявление новой?

T>Во-первых, вы проигнорировали "самое верхнее по дереву" или в данном случае это не поможет, а я не уследил почему именно?

ОК. У меня есть функция. Положим вообще объявленная как лямбда. Я могу ее вызвать в точке Х (до конструкции х = 4) или в точке У (после конструкции х = 4). В функции также содержится что-то типа х = бла-бла-бла. Как быть?
Смысл "=" определяется динамически в процессе исполения. var однозначен всегда. Нет var, то пока код не выполнится, я и не пойму, что там раньше, а что там позже.

T>Во-вторых, эту неоднозначность можно убрать семантически (о чём мы уже говорили выше). Например, можно (как в петоне) ввести правило: '=' всегда определяет имя в текущем скопе. В таком случае, кажется, дерево точно поможет найти объявление (первое определение).


А с замыканиями как быть? Как присвоить значение захваченной переменной? Ведь там абсолютно та же ерунда со скопами.
Re[17]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 04:38
Оценка:
ВВ>>>"=" может быть как декларацией, так и изменением существующего значения. Представь себе тело некоего замыкания вида { x = 2 }. Здесь что происходит? Изменение захваченной переменной? Объявление новой?
T>>Во-первых, вы проигнорировали "самое верхнее по дереву" или в данном случае это не поможет, а я не уследил почему именно?

ВВ>ОК. У меня есть функция. Положим вообще объявленная как лямбда. Я могу ее вызвать в точке Х (до конструкции х = 4) или в точке У (после конструкции х = 4). В функции также содержится что-то типа х = бла-бла-бла. Как быть?

ВВ>Смысл "=" определяется динамически в процессе исполения. var однозначен всегда. Нет var, то пока код не выполнится, я и не пойму, что там раньше, а что там позже.

Подытог.

1. var вы собираетесь использовать для того, чтобы во время компиляции строить оптимальную карту локальных переменных — массив вместо словаря.
2. Неупотребление var во врем компиляции вы ловить не собираетесь.
3. Смысл '=' определяется динамически.

Вот я наверное чего-то упускаю из вида, но по-моему 1 и 3 довольно противоречивы. И, конечно, обязательное ключевое слово в декларации вполне решает это противоречие, в одну сторону. В конце сообщения варианты для решения в другую сторону.

Я тут попробовал набросать вашу функцию (положим вообще лямбду ) в разных случаях и всё стало ясно, есть только один вопрос.

function (){ x = 10 }()
x = 4
return x

Допустим, будет объявлено имя x. Будет объявлена функция и она замкнётся на x из внешнего скопа.
Потом функция выполнится, присвоит x значение 10. Но после этого выполнится x = 4. Код вернёт 4.
А что при этом должна сделать функция { x++ } ?

T>>Во-вторых, эту неоднозначность можно убрать семантически (о чём мы уже говорили выше). Например, можно (как в петоне) ввести правило: '=' всегда определяет имя в текущем скопе. В таком случае, кажется, дерево точно поможет найти объявление (первое определение).


ВВ>А с замыканиями как быть? Как присвоить значение захваченной переменной? Ведь там абсолютно та же ерунда со скопами.


Например:
— Не присваивать новых значений захваченной переменной. (этот вариант мне больше всего нравится )
— В Python3 для этого ввели ключевое слово nonlocal.


Вот ещё нашёл предложение var в Python3: http://mail.python.org/pipermail/python-3000/2006-October/003968.html

P.S.: похоже, у вас довольно интересный проект. Исходники открыты?
Re[18]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 15:14
Оценка:
Здравствуйте, Temoto, Вы писали:
T>Подытог.

Смотри, тут c-smile по соседству хороший пример привел. var — это на самом деле своего рода читерство:

function Foo(y)
{
  x = 2; //переменная в локальном скопе

  if (y) {
     var x; //вот поэтому
  }
}


Ты ведь явно не ждешь такого же поведения от "="?
А с ним мы имеем прямо противоположную ситуацию:

if (someCondition)
  x = 2;

Foo();

function Foo()
{
  x = 3; //а тут что???
}


Как видишь, данный код уже полностью динамический. Что конкретно произойдет, понятно только при исполнении. someCondition — это, может быть, вообще какой-нибудь параметр, который передается извне.
Так что на мой взгляд тут нет какого-либо противоречия.

T>1. var вы собираетесь использовать для того, чтобы во время компиляции строить оптимальную карту локальных переменных — массив вместо словаря.

T>2. Неупотребление var во врем компиляции вы ловить не собираетесь.
T>3. Смысл '=' определяется динамически.

T>Вот я наверное чего-то упускаю из вида, но по-моему 1 и 3 довольно противоречивы. И, конечно, обязательное ключевое слово в декларации вполне решает это противоречие, в одну сторону. В конце сообщения варианты для решения в другую сторону.


Они не противоречивы по той простой причине, что смысл "=" статически определить просто нельзя. Ну нельзя и все тут. var определяется статически в виду того, что он просто обрабатывается особым образом. Пример от c-smile это прекрасно иллюстрирует.

T>Я тут попробовал набросать вашу функцию (положим вообще лямбду ) в разных случаях и всё стало ясно, есть только один вопрос.

T>function (){ x = 10 }()
T>x = 4
T>return x
T>Допустим, будет объявлено имя x. Будет объявлена функция и она замкнётся на x из внешнего скопа.
T>Потом функция выполнится, присвоит x значение 10. Но после этого выполнится x = 4. Код вернёт 4.
T>А что при этом должна сделать функция { x++ } ?

Данная функция, разумеется, вернет значение 4. А как еще может быть? Замыкание by design предполагает, что переменные не копируются в скоп функции, а именно захватываются ей. Т.е. обращение к ним происходит как бы по указателю.

T>>>Во-вторых, эту неоднозначность можно убрать семантически (о чём мы уже говорили выше). Например, можно (как в петоне) ввести правило: '=' всегда определяет имя в текущем скопе. В таком случае, кажется, дерево точно поможет найти объявление (первое определение).


Даже в таком случае не сможет, если это определение прячется за условие, которое может быть и не выполнено. Т.е. будет непонятно, вводить ли вообще такую переменную или нет, будет ли в таком-то выражении ошибка (типа unassigned variable 'x') или не будет. Для того, чтобы понять — надо просто выполнить код.

ВВ>>А с замыканиями как быть? Как присвоить значение захваченной переменной? Ведь там абсолютно та же ерунда со скопами.

T>Например:
T>- Не присваивать новых значений захваченной переменной. (этот вариант мне больше всего нравится )

Ну это получатся какие-то очень уж "чистые" замыкания Мне кажется, такие ограничения будут мешать. Все же люди привыкли пользоваться замыканиями в том числе и для изменения.

T>- В Python3 для этого ввели ключевое слово nonlocal.


Вообще тут получается забавный эффект.
Как только мы убираем var, у нас все функции — вуаля! — становятся недерминированными. Потому что сама семантика функции может поменяться в зависимости от того, вызовешь ли ты ее в точке А или в точке Б (до "=" или после). Причем самое тело ф-ции может быть "чистым" по самое не могу, что-то типа x => x + 2.

Для того, чтобы бороться с этим (непорядок ведь, да?), начинаем извращаться, придумываем новые ключевые слова, например, nonlocal Получается, что в одном месте мы ключевое слово (var) убрали, а в другом добавили. Причем все же для большинства программистов var-ы, джаваскрипты и прочие С-подобные синтаксисы вещи весьма привычные, ибо мейнстрим. А вот выкрутасы вроде nonlocal уже нет.

Наконец тут еще другая проблема вылезает. Вызов одной функции из другой. Ведь что такое функция? Это просто некоторое имя с особым значением типа "функция" и ничего более. Вводить для этого "особые" правила? Не вводить? А как быть с объектами хоста? Как в том же ДжаваСкрипте — есть объект window. Он в глобальном скопе. Тоже обычное такое имя. Особые правила? Без особых правил?

Можно, конечно, и на опыт того же питона опираться, но питон не вчера родился и при его развитии тоже много чего "переосмыслили".

T>Вот ещё нашёл предложение var в Python3: http://mail.python.org/pipermail/python-3000/2006-October/003968.html


Вот видишь, чуть копнешь, и не все так просто тут с этим var. И так не очень правильно, и сяк тоже не очень.

T>P.S.: похоже, у вас довольно интересный проект. Исходники открыты?


Ну пока нет, хотя думаю со временем открыть.
Re[19]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 15:59
Оценка:
ВВ>Они не противоречивы по той простой причине, что смысл "=" статически определить просто нельзя. Ну нельзя и все тут. var определяется статически в виду того, что он просто обрабатывается особым образом. Пример от c-smile это прекрасно иллюстрирует.

Пример от c-smile на жаваскрипте. Мы постоянно прыгаем с обсуждения жаваскрипта на обсуждение всех динамических языков на язык, который вы создаёте.
В жаваскрипте нельзя, потому что деструктивное присваивание. Если его убрать, то можно статически определить смысл '='.

T>>Я тут попробовал набросать вашу функцию (положим вообще лямбду ) в разных случаях и всё стало ясно, есть только один вопрос.

T>>function (){ x = 10 }()
T>>x = 4
T>>return x
T>>Допустим, будет объявлено имя x. Будет объявлена функция и она замкнётся на x из внешнего скопа.
T>>Потом функция выполнится, присвоит x значение 10. Но после этого выполнится x = 4. Код вернёт 4.
T>>А что при этом должна сделать функция { x++ } ?

ВВ>Данная функция, разумеется, вернет значение 4. А как еще может быть? Замыкание by design предполагает, что переменные не копируются в скоп функции, а именно захватываются ей. Т.е. обращение к ним происходит как бы по указателю.


А откуда она знает про 4, если присваивание 4 произошло после её вызова?

Тот же самый код другими словами:

var f = function() { x++ }
var x = input()
return x

T>>>>Во-вторых, эту неоднозначность можно убрать семантически (о чём мы уже говорили выше). Например, можно (как в петоне) ввести правило: '=' всегда определяет имя в текущем скопе. В таком случае, кажется, дерево точно поможет найти объявление (первое определение).


ВВ>Даже в таком случае не сможет, если это определение прячется за условие, которое может быть и не выполнено. Т.е. будет непонятно, вводить ли вообще такую переменную или нет, будет ли в таком-то выражении ошибка (типа unassigned variable 'x') или не будет. Для того, чтобы понять — надо просто выполнить код.


А какая вам разница будет ли выполнено *объявление*? Ну попадёт в *массив* (а не словарь) лишний пункт, который будет редко *присвоен*.

ВВ>>>А с замыканиями как быть? Как присвоить значение захваченной переменной? Ведь там абсолютно та же ерунда со скопами.

T>>Например:
T>>- Не присваивать новых значений захваченной переменной. (этот вариант мне больше всего нравится )

ВВ>Ну это получатся какие-то очень уж "чистые" замыкания Мне кажется, такие ограничения будут мешать. Все же люди привыкли пользоваться замыканиями в том числе и для изменения.


Это уже надо смотреть на аудиторию. Многим людям деструктивное присваивание мешает. То есть оно объективно мешает, потому что объективно допускает ряд ошибок. А у меня сложилось мнение, что вы многие ошибки (судя по такой насущной, как неиспользованный var) хотите переложить в рантайм.

T>>- В Python3 для этого ввели ключевое слово nonlocal.


ВВ>Вообще тут получается забавный эффект.

ВВ>Как только мы убираем var, у нас все функции — вуаля! — становятся недерминированными. Потому что сама семантика функции может поменяться в зависимости от того, вызовешь ли ты ее в точке А или в точке Б (до "=" или после). Причем самое тело ф-ции может быть "чистым" по самое не могу, что-то типа x => x + 2.

Это не из-за var. Это называется динамический скопинг, я сегодня в википедии читал. Действительно, динамический скопинг на корню убивает всю чистоту. Это одна из хороших причин делать лексический скопинг.

ВВ>Для того, чтобы бороться с этим (непорядок ведь, да?), начинаем извращаться, придумываем новые ключевые слова, например, nonlocal Получается, что в одном месте мы ключевое слово (var) убрали, а в другом добавили. Причем все же для большинства программистов var-ы, джаваскрипты и прочие С-подобные синтаксисы вещи весьма привычные, ибо мейнстрим. А вот выкрутасы вроде nonlocal уже нет.


var причислить к Си-подобным это сильно. И говорить за большинство программистов это как-то... ассемблер что-ли. Низкий уровень. Вы уж извините.
Если аудитория — сишарперы и жаваскриптеры, конечно, им привычнее var, чем nonlocal. А если программисты, то им надо задачу решать, а не в сортах ключевых слов ковыряться. Что дадут, на том и напишут.

Если б было равное соотношение где убрали и где добавили, то nonlocal был бы нонсенсом. Однако, на мой взгляд, в локальном скопе присваивают всё же чаще. Соответственно, опять же вопрос аудитории, только на этот раз кода. Если ваши программисты уверенно собираются писать больше присваиваний нелокальному скопу, то, конечно, var лучше подходит.

ВВ>Наконец тут еще другая проблема вылезает. Вызов одной функции из другой. Ведь что такое функция? Это просто некоторое имя с особым значением типа "функция" и ничего более. Вводить для этого "особые" правила? Не вводить? А как быть с объектами хоста? Как в том же ДжаваСкрипте — есть объект window. Он в глобальном скопе. Тоже обычное такое имя. Особые правила? Без особых правил?


Проблему не понял. Для чего надо вводить особые правила в случае с функцией и объектами хоста?

ВВ>Можно, конечно, и на опыт того же питона опираться, но питон не вчера родился и при его развитии тоже много чего "переосмыслили".


Может я неправильно понял, но в этом предложении разделительный союз "но" неуместен, потому что вторая часть как раз подтверждает, что на опыт питона полагаться можно.
С питоном ещё нужно учесть очень большой момент обратной совместимости. Новые проекты могут использовать "невчерашний опыт" во всю силу, не заботясь о существующей массе кода.

Кстати Io вы изучали?

T>>Вот ещё нашёл предложение var в Python3: http://mail.python.org/pipermail/python-3000/2006-October/003968.html

ВВ>Вот видишь, чуть копнешь, и не все так просто тут с этим var. И так не очень правильно, и сяк тоже не очень.

Не было мнения, что с ним очень просто. Я уже давно высказываю мысль, что можно сделать правильно и с var и без. Вариантов-то уйма.
Re[20]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 06.03.10 16:20
Оценка:
Здравствуйте, Temoto, Вы писали:

ВВ>>Они не противоречивы по той простой причине, что смысл "=" статически определить просто нельзя. Ну нельзя и все тут. var определяется статически в виду того, что он просто обрабатывается особым образом. Пример от c-smile это прекрасно иллюстрирует.

T>Пример от c-smile на жаваскрипте. Мы постоянно прыгаем с обсуждения жаваскрипта на обсуждение всех динамических языков на язык, который вы создаёте.
T>В жаваскрипте нельзя, потому что деструктивное присваивание. Если его убрать, то можно статически определить смысл '='.

Я пока не вижу как можно статически определить смысл "=". И нигде они статически не определяется.
А пример хоть и на джава-скрипте, но вполне типичный.

ВВ>>Данная функция, разумеется, вернет значение 4. А как еще может быть? Замыкание by design предполагает, что переменные не копируются в скоп функции, а именно захватываются ей. Т.е. обращение к ним происходит как бы по указателю.

T>А откуда она знает про 4, если присваивание 4 произошло после её вызова?

Как откуда? Я же тебе говорю — она *захватывает* эту переменную. Это замыкание, понимаешь? А не "закопирование". Считай, что со значением х данная функция работает через указатель.

T>>>>>Во-вторых, эту неоднозначность можно убрать семантически (о чём мы уже говорили выше). Например, можно (как в петоне) ввести правило: '=' всегда определяет имя в текущем скопе. В таком случае, кажется, дерево точно поможет найти объявление (первое определение).

ВВ>>Даже в таком случае не сможет, если это определение прячется за условие, которое может быть и не выполнено. Т.е. будет непонятно, вводить ли вообще такую переменную или нет, будет ли в таком-то выражении ошибка (типа unassigned variable 'x') или не будет. Для того, чтобы понять — надо просто выполнить код.
T>А какая вам разница будет ли выполнено *объявление*? Ну попадёт в *массив* (а не словарь) лишний пункт, который будет редко *присвоен*.

Разница огромная. Если объявление не выполнено, значит его не было, значит переменная не была "объявлена". Я тебя уже спрашивал, ты хочешь от "=" такого же поведения как и от var? Т.е. если где-то в коде, даже если этот код никогда не выполняется, прячется x = 1, то мы считаем, что х в этом скопе? Это очень странное поведение на мой взгляд — и совершенно неожиданное для большинства пользователей.

Наконец я не могу пихать в карту то, чего на самом деле может и не быть. В таком случая я при исполнении даже банальных ошибок вроде unassigned variable 'x' не смогу сгенерировать.

T>Это уже надо смотреть на аудиторию. Многим людям деструктивное присваивание мешает. То есть оно объективно мешает, потому что объективно допускает ряд ошибок. А у меня сложилось мнение, что вы многие ошибки (судя по такой насущной, как неиспользованный var) хотите переложить в рантайм.


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

ВВ>>Вообще тут получается забавный эффект.

ВВ>>Как только мы убираем var, у нас все функции — вуаля! — становятся недерминированными. Потому что сама семантика функции может поменяться в зависимости от того, вызовешь ли ты ее в точке А или в точке Б (до "=" или после). Причем самое тело ф-ции может быть "чистым" по самое не могу, что-то типа x => x + 2.
T>Это не из-за var. Это называется динамический скопинг, я сегодня в википедии читал. Действительно, динамический скопинг на корню убивает всю чистоту. Это одна из хороших причин делать лексический скопинг.

var тем не менее помогает от этой проблемы уйти и без лексического скопинга. Фактически мы имеем гибридный скопинг если хочешь.

ВВ>>Для того, чтобы бороться с этим (непорядок ведь, да?), начинаем извращаться, придумываем новые ключевые слова, например, nonlocal Получается, что в одном месте мы ключевое слово (var) убрали, а в другом добавили. Причем все же для большинства программистов var-ы, джаваскрипты и прочие С-подобные синтаксисы вещи весьма привычные, ибо мейнстрим. А вот выкрутасы вроде nonlocal уже нет.

T>var причислить к Си-подобным это сильно. И говорить за большинство программистов это как-то... ассемблер что-ли. Низкий уровень. Вы уж извините.
T>Если аудитория — сишарперы и жаваскриптеры, конечно, им привычнее var, чем nonlocal. А если программисты, то им надо задачу решать, а не в сортах ключевых слов ковыряться. Что дадут, на том и напишут.

Причем тут ассемблер? Синтаксис у ДжаваСкрипта Си-подобный, что совершенно не значит, что семантически язык должен быть похож на Си. Речь о синтаксисе.
Есть еще вопросы удобства и привычности.
А пока по факту получается, что какие-то ключевые слова для аннотирования имен все же необходимы.

ВВ>>Наконец тут еще другая проблема вылезает. Вызов одной функции из другой. Ведь что такое функция? Это просто некоторое имя с особым значением типа "функция" и ничего более. Вводить для этого "особые" правила? Не вводить? А как быть с объектами хоста? Как в том же ДжаваСкрипте — есть объект window. Он в глобальном скопе. Тоже обычное такое имя. Особые правила? Без особых правил?

T>Проблему не понял. Для чего надо вводить особые правила в случае с функцией и объектами хоста?

Для удобства. Все вещи живут в глобальном скопе. Делать дополнительные телодвижения при работе с ними не хочется.

ВВ>>Можно, конечно, и на опыт того же питона опираться, но питон не вчера родился и при его развитии тоже много чего "переосмыслили".

T>Может я неправильно понял, но в этом предложении разделительный союз "но" неуместен, потому что вторая часть как раз подтверждает, что на опыт питона полагаться можно.
T>С питоном ещё нужно учесть очень большой момент обратной совместимости. Новые проекты могут использовать "невчерашний опыт" во всю силу, не заботясь о существующей массе кода.

"Но" в данном случае означает, что в сегодняшнем Питоне многое осталось "в наследство" и нужно аккуратно подходить к этому вопросу — что живет в порядке совместимости, а что действительно является интересным решением.

T>Кстати Io вы изучали?


Смотрел поверхностно, но нет, не изучал.
Re[21]: Динамические языки и переменные
От: Temoto  
Дата: 06.03.10 16:50
Оценка:
ВВ>Я пока не вижу как можно статически определить смысл "=". И нигде они статически не определяется.

Но я же писал как можно определить. Если лексический скопинг, то по дереву пройтись вверх надо и найдётся смысл присваивания. Там возникают вопросы с присваиванием нелокальному скопу, но задача статически определить смысл присваивания всё-таки решаема.
В общем случае нельзя определить, согласен. Уже хотя бы потому что с динамическим скопом смысл присваивания может зависеть от IO.

ВВ>>>Данная функция, разумеется, вернет значение 4. А как еще может быть? Замыкание by design предполагает, что переменные не копируются в скоп функции, а именно захватываются ей. Т.е. обращение к ним происходит как бы по указателю.

T>>А откуда она знает про 4, если присваивание 4 произошло после её вызова?

ВВ>Как откуда? Я же тебе говорю — она *захватывает* эту переменную. Это замыкание, понимаешь? А не "закопирование". Считай, что со значением х данная функция работает через указатель.


В приведённом коде функция вызвана до того, как значение по указателю было положено. Я уже и так и сяк пишу, чтоб обратить на это внимание. Уже по-русски написал, всё равно непонимание.

T>>А какая вам разница будет ли выполнено *объявление*? Ну попадёт в *массив* (а не словарь) лишний пункт, который будет редко *присвоен*.


ВВ>Разница огромная. Если объявление не выполнено, значит его не было, значит переменная не была "объявлена". Я тебя уже спрашивал, ты хочешь от "=" такого же поведения как и от var? Т.е. если где-то в коде, даже если этот код никогда не выполняется, прячется x = 1, то мы считаем, что х в этом скопе? Это очень странное поведение на мой взгляд — и совершенно неожиданное для большинства пользователей.


Что вы скажете по поводу такого кода?

// здесь ещё 10 строк
if cond: return 100500
// и здесь ещё 10 строк
var x = 10
return -1

ВВ>Наконец я не могу пихать в карту то, чего на самом деле может и не быть. В таком случая я при исполнении даже банальных ошибок вроде unassigned variable 'x' не смогу сгенерировать.


x не попадёт в карту из-за if?

T>>Это уже надо смотреть на аудиторию. Многим людям деструктивное присваивание мешает. То есть оно объективно мешает, потому что объективно допускает ряд ошибок. А у меня сложилось мнение, что вы многие ошибки (судя по такой насущной, как неиспользованный var) хотите переложить в рантайм.


ВВ>Ну так динамический язык, большинство ошибок обычно и вылезают в рантайме. По той простой причине, что в компайл-тайме нам просто неизвестно, что в действительности произойдет.

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

Где я говорил, что мне нравится Python? Он очень динамический. Слишком. Компайл-тайма в питоне, кстати, семантически нет.

ВВ>var тем не менее помогает от этой проблемы уйти и без лексического скопинга. Фактически мы имеем гибридный скопинг если хочешь.


На эту тему вам выше дали отличный совет, что надо делать либо такой, либо такой. У строгого выбора есть ещё такой побочный плюс, что дороги обоих утоптаны с кровью и слезами. Хотя, если у вас исследовательский проект, а не задачу решить, то, конечно, всё наоборот.

T>>И говорить за большинство программистов это как-то... ассемблер что-ли. Низкий уровень. Вы уж извините.

ВВ>Причем тут ассемблер?

Это я так пошутить попытался. Если серьёзно, то говорить за большинство программистов — это несерьёзный разговор.

ВВ>>>Наконец тут еще другая проблема вылезает. Вызов одной функции из другой. Ведь что такое функция? Это просто некоторое имя с особым значением типа "функция" и ничего более. Вводить для этого "особые" правила? Не вводить? А как быть с объектами хоста? Как в том же ДжаваСкрипте — есть объект window. Он в глобальном скопе. Тоже обычное такое имя. Особые правила? Без особых правил?

T>>Проблему не понял. Для чего надо вводить особые правила в случае с функцией и объектами хоста?

ВВ>Для удобства. Все вещи живут в глобальном скопе. Делать дополнительные телодвижения при работе с ними не хочется.


Аа.. вы имеете в виду nonlocal window = new Window()?
Так ведь nonlocal нужен только для присваивания. Вы когда-нибудь видели, чтобы window присваивали? Я нет.

ВВ>"Но" в данном случае означает, что в сегодняшнем Питоне многое осталось "в наследство" и нужно аккуратно подходить к этому вопросу — что живет в порядке совместимости, а что действительно является интересным решением.


Да, мы часто об одном говорим разными словами.
Re[22]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 08.03.10 13:20
Оценка:
Здравствуйте, Temoto, Вы писали:

ВВ>>Я пока не вижу как можно статически определить смысл "=". И нигде они статически не определяется.

T>Но я же писал как можно определить. Если лексический скопинг, то по дереву пройтись вверх надо и найдётся смысл присваивания. Там возникают вопросы с присваиванием нелокальному скопу, но задача статически определить смысл присваивания всё-таки решаема.
T>В общем случае нельзя определить, согласен. Уже хотя бы потому что с динамическим скопом смысл присваивания может зависеть от IO.

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

x = 1;

...
{
  x = 2;//тут я хотел объявить новую переменную, но забыл, что такая уже есть
}


А с var будет довольно полезная ошибка.

ВВ>>Как откуда? Я же тебе говорю — она *захватывает* эту переменную. Это замыкание, понимаешь? А не "закопирование". Считай, что со значением х данная функция работает через указатель.

T>В приведённом коде функция вызвана до того, как значение по указателю было положено. Я уже и так и сяк пишу, чтоб обратить на это внимание. Уже по-русски написал, всё равно непонимание.

А какое ты поведение ожидаешь? Мы ведь уже определились, что var — это очень хитрая конструкция. По сути неважно, где она находится. Если var в принципе есть, то у нас заводится переменная, под нее как бы выделяется своя "ячейка памяти", при этом совершенно неважно было ли туда явно записано какое-то значение или нет. Замыкание в данном случае просто получает указатель на эту ячейку и работает с ней.
Ведь тебя же не удивит, если ты изменишь значение захваченной переменной, и она изменится в замыкании тоже.

T>Что вы скажете по поводу такого кода?


T>// здесь ещё 10 строк

T>if cond: return 100500
T>// и здесь ещё 10 строк
T>var x = 10
T>return -1

Такой код, может быть, и не очень красив, но по крайней мере более привычен, что ли. Во всяком случае на мой взгляд.
А "чистый", без добавок, динамический скоп все же ИМХО довольно тяжелая штука.

ВВ>>Наконец я не могу пихать в карту то, чего на самом деле может и не быть. В таком случая я при исполнении даже банальных ошибок вроде unassigned variable 'x' не смогу сгенерировать.

T>x не попадёт в карту из-за if?

Ну да

ВВ>>Ну так динамический язык, большинство ошибок обычно и вылезают в рантайме. По той простой причине, что в компайл-тайме нам просто неизвестно, что в действительности произойдет.

ВВ>>Тебе вот вроде нравится Питон, так там вообще считается, что нельзя полагаться на то, что модули, доступные в компайл-тайме, это те же модули, что и в ран-тайме. И как тут ошибки генерить?
T>Где я говорил, что мне нравится Python? Он очень динамический. Слишком. Компайл-тайма в питоне, кстати, семантически нет.

Как нет? Виртуальная машина-то там есть. Я компайл таймом называю тот этап когда на основе AST формируются инструкции для виртуального процесса. Такой этап там есть.
Это вот Руби напрямую по AST фигачит, но это какой-то жуткий способ ИМХО.

ВВ>>var тем не менее помогает от этой проблемы уйти и без лексического скопинга. Фактически мы имеем гибридный скопинг если хочешь.

T>На эту тему вам выше дали отличный совет, что надо делать либо такой, либо такой. У строгого выбора есть ещё такой побочный плюс, что дороги обоих утоптаны с кровью и слезами. Хотя, если у вас исследовательский проект, а не задачу решить, то, конечно, всё наоборот.

В принципе да. Уж что точно не стоит делать, это вводиться некий полу-динамический скоп, а потом как во многих языках специальные конструкции для объявления переменных в лексическом скопе. Это ИМХО как раз тот пример, на который смотреть не стоит.

T>Аа.. вы имеете в виду nonlocal window = new Window()?

T>Так ведь nonlocal нужен только для присваивания. Вы когда-нибудь видели, чтобы window присваивали? Я нет.

А вот так:
window.document.body.onload = function() {...}?
Re[23]: Динамические языки и переменные
От: Temoto  
Дата: 08.03.10 16:45
Оценка:
ВВ>Ну лексический скопинг все меняет. При лексическом-то, мне кажется, var становится нужен уже не компилятору, а программисту — чтобы глазами не выискивать, где там первый "=". Плюс ты декларируешь свои намерения явно:
ВВ>А с var будет довольно полезная ошибка.

Да, это был ваш второй пункт про опечатки. Ошибка полезная, спору нет. Только дело в том, что любой код заведомо *может* отличаться от намерений. То есть я могу написать var, а намерение было изменить существующую переменную.

За отсутствием более мощных инструментов отлова ошибок, конечно такое использование var может оказаться весьма полезным в каком-то конкретном языке.

ВВ>>>Как откуда? Я же тебе говорю — она *захватывает* эту переменную. Это замыкание, понимаешь? А не "закопирование". Считай, что со значением х данная функция работает через указатель.

T>>В приведённом коде функция вызвана до того, как значение по указателю было положено. Я уже и так и сяк пишу, чтоб обратить на это внимание. Уже по-русски написал, всё равно непонимание.

ВВ>А какое ты поведение ожидаешь? Мы ведь уже определились, что var — это очень хитрая конструкция. По сути неважно, где она находится. Если var в принципе есть, то у нас заводится переменная, под нее как бы выделяется своя "ячейка памяти", при этом совершенно неважно было ли туда явно записано какое-то значение или нет. Замыкание в данном случае просто получает указатель на эту ячейку и работает с ней.

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

Я бы ожидал ошибку компиляции, дескать значение ещё не инициализировано.

T>>Что вы скажете по поводу такого кода?


T>>// здесь ещё 10 строк

T>>if cond: return 100500
T>>// и здесь ещё 10 строк
T>>var x = 10
T>>return -1

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

ВВ>А "чистый", без добавок, динамический скоп все же ИМХО довольно тяжелая штука.

Да не в красоте дело, я про потенциальное неиспользование. И я не дразню, я правда спрашиваю.
Смысл этого кода в том, что вам придётся класть в карту локалей потенциально неиспользуемую переменную. А чуть выше вы говорили, что так делать конечно же нельзя. ("Наконец я не могу пихать в карту то, чего на самом деле может и не быть"). И вот мне интересно как (и зачем) ловить ситуации, как в вышеприведённом коде.

ВВ>Как нет? Виртуальная машина-то там есть. Я компайл таймом называю тот этап когда на основе AST формируются инструкции для виртуального процесса. Такой этап там есть.

ВВ>Это вот Руби напрямую по AST фигачит, но это какой-то жуткий способ ИМХО.

$ echo 'print "foobar"' > compile_test.py
$ python compile_test.py
foobar
$ ls compile_test*
compile_test.py

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

T>>Аа.. вы имеете в виду nonlocal window = new Window()?

T>>Так ведь nonlocal нужен только для присваивания. Вы когда-нибудь видели, чтобы window присваивали? Я нет.

ВВ>А вот так:

ВВ>window.document.body.onload = function() {...}?

Здесь присваивают (кому) onload, а не window. Всё, что до .onload заменяет nonlocal, в смысле указывает в каком скопе нужно создать/изменить переменную. Причём, конкретно указывает. После nonlocal ещё поискать надо во всех внешних скопах, а тут сразу известно.

Вы с самого начала приводили примеры про this и Foo() и для меня это каждый раз было странно. Потому что я вижу x = 1 и obj.x = 1 как абсолютно разные конструкции. x = 1 может иметь обсуждаемые тут проблемы скопа, потому что может быть чётко неясно в каком именно скопе нужно создать или изменить переменную x. obj.x = 1 этой проблемы (на мой взгляд) лишён, потому что программист явно пишет в каком скопе нужно создать/модифицировать x.

То есть, можно провести такую аналогию, если добавить лишнего гемора в код:

global.x = 1

function f() {
f.x = 2
function g() {
g.x = 3
f.x = g.x — 1
}
return global.x + f.x
}

Здесь нет неоднозначности. Точно так же её нет и в случае obj.x = 1 в жаваскрипте.

Если хочется неоднозначность придумать, то единственное, что мне приходит в голову, это то, что надо читать

nonlocal window.document.body.onload = function() {...}

как создание *нового* window
(с одним аттрибутом document
(с одним аттрибутом body
(с одним аттрибутом onload равным function...)
)
) и замену существующего глобального window, этим новым. Но это ведь бред. Даже писать этот бред не стоило.
Re[3]: Динамические языки и переменные
От: c-smile Канада http://terrainformatica.com
Дата: 08.03.10 17:39
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, c-smile, Вы писали:


CS>>Кстати в javascript как и в питоне есть такая грустная фенечка:


ВВ>Мы тут подобное обсуждали. В принципе поведение вполне ожидаемое для динамического скопа, с учетом того, что объявление переменной вида "var y" по сути скорее инструкция для компилятора (добавить имя y в карту переменных), чем некий исполняемый код. Потому и по фиг в принципе, где она находится.


"вполне ожидаемое"?

Назови любой другой язык использующий C syntax в котором последующие декларации изменяют смысл предыдуших statements.

ВВ>А у тебя как?


У меня как в C/C++/C#/Java. Т.е. "var y" локальна блоку в котором она содержится.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.