Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 15:46
Оценка:
Вопрос такой.
Многие динамические языки позволяют неявно объявлять переменные (некоторые даже и вовсе не имеют синтаксиса для явного объявления, но это другой вопрос).
При этом в ряде случае такое объявление не рекомендуется.

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

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


Если рассматривать проблему с т.з. ДжаваСкрипта, то там и вовсе становится непонятно, зачем нужна возможность неявного объявления. Я, к примеру, так не пишу никогда.
Но с другой стороны вышеуказанный пример и:

var obj = {};
...
obj.y = 2;


Вещи в принципе родственные.

Собственно, мой вопрос, как вы считаете — если в языке есть синтаксис для явного объявления переменных, насколько необходима поддержка неявного объявления? Если эту возможность убрать (т.е. в примере выше была бы ошибка) потеряет ли язык в выразительности?
Re: Динамические языки и переменные
От: SE Украина  
Дата: 05.03.10 15:58
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


Вот такая запись, это явное или неявное объявление?

function Foo()
{
  this.x = 1; // переменная в скопе Foo, охраняющая свое значение между вызовами
}



Язык сильно бы обеднел без closure'ов.
Re: Динамические языки и переменные
От: Mr.Cat  
Дата: 05.03.10 16:11
Оценка: 9 (1) +1
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Собственно, мой вопрос, как вы считаете — если в языке есть синтаксис для явного объявления переменных, насколько необходима поддержка неявного объявления? Если эту возможность убрать (т.е. в примере выше была бы ошибка) потеряет ли язык в выразительности?
Ящитаю, должно быть понятие биндинга значения к имени:
— Лексический, т.е. биндинг действует в пределах блока кода.
— Динамический, биндинг действует в пределах дерева вызовов.
Общефилософские рассуждения на этот счет можно почитать тут: http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf (одна из lambda papers за авторством Стила и Сассмана).
Re[2]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 16:16
Оценка:
Здравствуйте, SE, Вы писали:

SE>Вот такая запись, это явное или неявное объявление?


SE>
SE>function Foo()
SE>{
SE>  this.x = 1; // переменная в скопе Foo, охраняющая свое значение между вызовами
SE>}
SE>


Данная запись аналогична:

function GetFoo()
{
  var x = 1;
  return function() { return ++x; }
}


Или что-то в этом роде.
Но речь не о ДжаваСкрипте в общем-то. Мне как раз кажется, что эти вещи в JS сделаны не слишком прозрачно.

Но ведь все равно мы имеет три семантически разные записи:

1. var x = 1;
2. x = 1;
3. this.x = 1;


Отвечая на ваш вопрос, я скажу, что нет — это не явное и не неявное объявление. Это объявление "третьего вида" Но это есть особенность конкретного языка. И насколько даже в этом конкретном языка нужна запись #2? Т.е. она полезна в каких-то случаях? Устроил бы вас лично язык, где переменные нужно было бы декларировать всегда явно?

SE>Язык сильно бы обеднел без closure'ов.


ИМХО для замыканий this не нужен, он нужен для имитации классов на замыканиях. Но это совсем другая тема.
Re[2]: Динамические языки и переменные
От: Mr.Cat  
Дата: 05.03.10 16:16
Оценка:
Здравствуйте, Mr.Cat, Вы писали:
MC>- Лексический, т.е. биндинг действует в пределах блока кода.
MC>- Динамический, биндинг действует в пределах дерева вызовов.
Добавлю, что все остальное есть ересь и должно искореняться, т.к., на мой взгляд, программист может эффективно анализировать код с точки зрения исходного кода, либо деревьев вызова. Остальные зависимости семантики того или иного действия от состояния программы я считаю трудными для понимания.
Re[2]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 16:22
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

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

MC>Ящитаю, должно быть понятие биндинга значения к имени:
MC>- Лексический, т.е. биндинг действует в пределах блока кода.
MC>- Динамический, биндинг действует в пределах дерева вызовов.
MC>Общефилософские рассуждения на этот счет можно почитать тут: http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf (одна из lambda papers за авторством Стила и Сассмана).

За ссылку спасибо, почитаю, но на первый взгляд не очень ясно, какая тут связь с неявным объявлением.

Я спрашиваю из практических соображений. Например, если делать все объявления явными, то карта локалей становится известна уже на этапе парсинга. Динамическое объявление сильно усложняет процесс, однако бенефиты его мне несильно видны. Но, возможно, я упускаю что-то...
Re[3]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 16:24
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Здравствуйте, Mr.Cat, Вы писали:

MC>>- Лексический, т.е. биндинг действует в пределах блока кода.
MC>>- Динамический, биндинг действует в пределах дерева вызовов.
MC>Добавлю, что все остальное есть ересь и должно искореняться, т.к., на мой взгляд, программист может эффективно анализировать код с точки зрения исходного кода, либо деревьев вызова. Остальные зависимости семантики того или иного действия от состояния программы я считаю трудными для понимания.

ОК, ну т.е. решение в ДжаваСкрипте с твоей точки зрения неправильное? Как правильно? Вообще убрать неявное объявление? Приравнять его к явному (тогда неясно, зачем нужно явное).
Re: Динамические языки и переменные
От: Temoto  
Дата: 05.03.10 17:27
Оценка:
ВВ>Вопрос такой.
ВВ>Многие динамические языки позволяют неявно объявлять переменные (некоторые даже и вовсе не имеют синтаксиса для явного объявления, но это другой вопрос).
ВВ>При этом в ряде случае такое объявление не рекомендуется.

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


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


var x = 1; явно присваивает имени x значение 1
var obj = {}; явно присваивает имени obj значение {} (пустой объект/словарь)

Что такое "неявное" объявление?
Если obj.x = 2 это неявное объявление obj={}, то как этот термин применим к остальным типам? x + 8 неявно объявляет x=0?
Re[2]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 17:37
Оценка:
Здравствуйте, Temoto, Вы писали:

T>var x = 1; явно присваивает имени x значение 1

T>var obj = {}; явно присваивает имени obj значение {} (пустой объект/словарь)
T>Что такое "неявное" объявление?

Вот полный текст программы:

var x = 1; //Явное объявление
y = 2; //Неявное объявление


Если ты знаешь термин лучше, обязательно возьму его на вооружение.

T>Если obj.x = 2 это неявное объявление obj={},


Ты не понял пример. Сам obj объявлен явно. Однако динамическое добавление поля к obj — процедура родственная неявному объявлению переменной. Особенно если рассматривать объект как ту же функцию, просто с захваченным контекстом.

var f = new Foo();
var x = f.x; //явно
f.y = x; //неявно

function Foo() {
  this.x = 2;
}


T>то как этот термин применим к остальным типам? x + 8 неявно объявляет x=0?


x + 8 без объявления x приводит к ошибке. Данное поведение мне кажется правильным и сомнений не вызывает.

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

Не противоречит ли явное объявление переменных (не говоря уж об обязательном явном объявлении) самой "природе" динамических языков? Дело в том, что когда все определение статичны это позволяет сделать серьезные оптимизации в карте локалей. Например, ассоциативный массив или мап можно менять индексированным массивом — и получаем ракету. Но с т.з. дизайна языка — правильно ли это?
Re[3]: Динамические языки и переменные
От: Temoto  
Дата: 05.03.10 19:06
Оценка:
T>>var x = 1; явно присваивает имени x значение 1
T>>var obj = {}; явно присваивает имени obj значение {} (пустой объект/словарь)
T>>Что такое "неявное" объявление?

ВВ>Вот полный текст программы:


ВВ>
ВВ>var x = 1; //Явное объявление
ВВ>y = 2; //Неявное объявление
ВВ>


ВВ>Если ты знаешь термин лучше, обязательно возьму его на вооружение.


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

T>>Если obj.x = 2 это неявное объявление obj={},


ВВ>Ты не понял пример. Сам obj объявлен явно. Однако динамическое добавление поля к obj — процедура родственная неявному объявлению переменной. Особенно если рассматривать объект как ту же функцию, просто с захваченным контекстом.


ВВ>
ВВ>var f = new Foo();
ВВ>var x = f.x; //явно
ВВ>f.y = x; //неявно

ВВ>function Foo() {
ВВ>  this.x = 2;
ВВ>}
ВВ>


Явное определение новых полей было бы var obj.new_field = 10 или что?

В динамических языках x = 10 следует читать как вызов функции set_global_var('x', 10). Не уверен, становится от этого понятнее или только запутаннее.

T>>то как этот термин применим к остальным типам? x + 8 неявно объявляет x=0?


ВВ>x + 8 без объявления x приводит к ошибке. Данное поведение мне кажется правильным и сомнений не вызывает.


ВВ>Мне интересно другое.

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

Да, про имена всё верно.
На этот счёт есть два термина declaration и definition. Первый объявляет и ничего более, второй присваивает имени значение. В известных мне динамических языках declaration отсутствует.

ВВ>Не противоречит ли явное объявление переменных (не говоря уж об обязательном явном объявлении) самой "природе" динамических языков? Дело в том, что когда все определение статичны это позволяет сделать серьезные оптимизации в карте локалей. Например, ассоциативный массив или мап можно менять индексированным массивом — и получаем ракету. Но с т.з. дизайна языка — правильно ли это?


Один мужик делал исследование на тему статических аннотаций (включая, но не только, типы) в питоне. Вот ссылка, если интересно http://npcontemplation.blogspot.com/2008/06/want-to-make-dynamic-languages-faster.html
Говорить за дизайн всех динамических языков было бы странно. Но неформально у каждого языка есть некоторый "интерфейс" (семантика), то есть ожидаемое поведение записанных на нём программ (в широком смысле, "5" это тоже программа на javascript). И можно говорить о том, нарушает ли конкретная оптимизация ожидаемое поведение, то есть ломает ли хотя бы одну корректную программу. Вот пример с мапом, на мой взгляд, не нарушает семантику жаваскрипта, потому что (подкожная реализация мапа и так скрыта от программиста) и ( нет формального требования к производительности доступа к полям мапов).
Re[3]: Динамические языки и переменные
От: FR  
Дата: 05.03.10 19:07
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>
ВВ>1. var x = 1;
ВВ>2. x = 1;
ВВ>3. this.x = 1;
ВВ>


ВВ>Отвечая на ваш вопрос, я скажу, что нет — это не явное и не неявное объявление. Это объявление "третьего вида" Но это есть особенность конкретного языка. И насколько даже в этом конкретном языка нужна запись #2? Т.е. она полезна в каких-то случаях? Устроил бы вас лично язык, где переменные нужно было бы декларировать всегда явно?



Это объявление "третьего вида" не особенность JavaScript в питоне все также.
Re[4]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 19:12
Оценка:
Здравствуйте, FR, Вы писали:

FR>Это объявление "третьего вида" не особенность JavaScript в питоне все также.


Ну хорошо, а что это меняет? Объективной необходимости в этом нет, можно спокойно обойтись и без this. Да и вопроса о неявном объявлении сей факт никак не отменяет.
Re[4]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 19:29
Оценка:
Здравствуйте, Temoto, Вы писали:

ВВ>>
ВВ>>var x = 1; //Явное объявление
ВВ>>y = 2; //Неявное объявление
ВВ>>

T>В жаваскрипте это называется локальные и глобальные переменные.

Если вышеприведенный код в глобальном скопе, то обе переменные — глобальные. Плюс это есть особенность ДжаваСкрипта. Никто в случае y = 2 не мешал бы создавать переменную в текущем скопе.

T>>>Если obj.x = 2 это неявное объявление obj={},


ВВ>>Ты не понял пример. Сам obj объявлен явно. Однако динамическое добавление поля к obj — процедура родственная неявному объявлению переменной. Особенно если рассматривать объект как ту же функцию, просто с захваченным контекстом.


ВВ>>
ВВ>>var f = new Foo();
ВВ>>var x = f.x; //явно
ВВ>>f.y = x; //неявно

ВВ>>function Foo() {
ВВ>>  this.x = 2;
ВВ>>}
ВВ>>


T>Явное определение новых полей было бы var obj.new_field = 10 или что?


Нет. Явное определение поля показано в теле Foo.
Явное == статическое, которое "видно" еще при разборе дерева.
Неявное == динамическое, когда становится понятно, что в результате выполнение выражения у нас появится новое поле.

T>В динамических языках x = 10 следует читать как вызов функции set_global_var('x', 10). Не уверен, становится от этого понятнее или только запутаннее.


Ну и о чем это говорит? Поведение set_global_var может быть каким угодно, в т.ч. и генерировать исключение, если x не была объявлена специальным образом ранее.

T>Да, про имена всё верно.

T>На этот счёт есть два термина declaration и definition. Первый объявляет и ничего более, второй присваивает имени значение. В известных мне динамических языках declaration отсутствует.

Гм, неужели ты не знаешь тот же ДжаваСкрипт? Это объясняет некоторое недопонимание. Все примеры, которые я приводил, это валидный джава-скрипт, с помощью которого я пытался иллюстрировать свою мысль.

Но дело на самом деле не в ДжаваСкрипте. И не в каком-то конкретном языке. Вопрос в другом.

В динамическом языке (предположим, что мы проектируем язык), где переменная рассматривается как имя-для-значения, необходимость явного указания списка имен, которые мы можем использовать, приведет к каким-либо ограничениям в использовании? Создаст ли это проблемы или значительное неудобство.
Положим, при первом обращении к имени всегда необходимо указывать var. Первое обращение должно либо представлять собой присвоение, либо просто содержать ключевое слово var и имя.
Re[5]: Динамические языки и переменные
От: Temoto  
Дата: 05.03.10 20:03
Оценка:
T>>Явное определение новых полей было бы var obj.new_field = 10 или что?

ВВ>Нет. Явное определение поля показано в теле Foo.

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

В динамических языках нет статических определений. Поэтому они (языки) так и названы.

и var x = 1 и x = 1 одинаково видны при разборе дерева и одинаково возымеют какой-то эффект только при выполнении.

Чтобы объект Foo появился в скопе, нужно сначала выполнить код, его определяющий.

В питоне разница между объектами и функциями более явная. Вот пример:

class Foo(object):
  def __init__(self):
    self.x = 10


Может казаться, что объявление Foo каким-то образом статичное или его лучше видно при разборе дерева, это не так. Чтобы сделать foo = Foo(), нужно сначала *выполнить* эти три строки выше, чтобы в текущем (или глобальном) скопе появилось имя Foo. Так вот в жаваскрипте всё точно так же. Нет ничего статичного, то есть известного до выполнения.

Ещё пример:

// в глобальном скопе
if (x < 10) {
  function Foo() { this.x = 2; }
} else {
  function Foo() { this.x = 5; }
}
foo = new Foo();


T>>Да, про имена всё верно.

T>>На этот счёт есть два термина declaration и definition. Первый объявляет и ничего более, второй присваивает имени значение. В известных мне динамических языках declaration отсутствует.

ВВ>Гм, неужели ты не знаешь тот же ДжаваСкрипт? Это объясняет некоторое недопонимание. Все примеры, которые я приводил, это валидный джава-скрипт, с помощью которого я пытался иллюстрировать свою мысль.


Javascript вроде знаю. Что примеры — валидный жаваскрипт понимаю. Мысль (попытку разделить определения на явные и неявные) не понимаю.

ВВ>Но дело на самом деле не в ДжаваСкрипте. И не в каком-то конкретном языке. Вопрос в другом.


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

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

Разница с текущим жаваскриптом предлагается в том, чтобы заставить перед каждым именем писать var, таким образом, исключив возможность в функциях менять глобальные переменные? Потому что кроме этого всё так и есть прямо сейчас. Даже "просто ключевое слово var и имя".

> function f() { var x; return x; }; f()
undefined
Re[6]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 20:39
Оценка:
Здравствуйте, Temoto, Вы писали:

T>В динамических языках нет статических определений. Поэтому они (языки) так и названы.


Даже в динамических языках есть статические определения. По крайней мере в некоторых. В том же ДжаваСкрипте, если знаешь, такой вызов функции вполне легален:

Foo();

function Foo() {}


А ведь выполнение до функции Foo еще не дошло. Хотя в том же Руби такое уже не прокатит.
В ДжаваСкрипте еще до выполнения объявлении функций вида function statement известны. А вот function expression, конечно, полностью динамические.
Но вопрос не этом.

Динамика не обязательно исключает любую статику. Точно также как динамический скоп может иметь некоторые черты лексического (например, переменные объявленные в теле функций являются локальными и не видны в глобальном скопе).

T>и var x = 1 и x = 1 одинаково видны при разборе дерева и одинаково возымеют какой-то эффект только при выполнении.


Какой эффект при исполнении должно возыметь:

var x;


Эта конструкция нужна скорее на этапе сборки для выстраивания карты локалей.

T>Чтобы объект Foo появился в скопе, нужно сначала выполнить код, его определяющий.


Как видишь, с примером функции Foo это не так.

ВВ>>Гм, неужели ты не знаешь тот же ДжаваСкрипт? Это объясняет некоторое недопонимание. Все примеры, которые я приводил, это валидный джава-скрипт, с помощью которого я пытался иллюстрировать свою мысль.

T>Javascript вроде знаю. Что примеры — валидный жаваскрипт понимаю. Мысль (попытку разделить определения на явные и неявные) не понимаю.

Тогда почему ты написал, что не знаешь динамические языки с явной декларацией переменных?

T>Разница с текущим жаваскриптом предлагается в том, чтобы заставить перед каждым именем писать var, таким образом, исключив возможность в функциях менять глобальные переменные? Потому что кроме этого всё так и есть прямо сейчас. Даже "просто ключевое слово var и имя".


А причем тут глобальные переменные? Мне упорно кажется, что у тебя неправильное понимание чего-то. К изменению глобальных переменных var никакого отношения не имеет. Ты можешь их спокойно менять.

var x = 0;

function Foo()
{
  x = 1;
}


При перекрытии локальными можно ввести ключевое слово base:

var x = 0;

function Foo()
{
  var x = 1;
  base.x = 2;
}


T>
>> function f() { var x; return x; }; f()
T>undefined
T>


Что значит этот пример? Ты объявил переменную, не присвоил значение (ее значение undefined). Что удивляет?
Re[7]: Динамические языки и переменные
От: Temoto  
Дата: 05.03.10 21:21
Оценка:
T>>В динамических языках нет статических определений. Поэтому они (языки) так и названы.

ВВ>Даже в динамических языках есть статические определения. По крайней мере в некоторых. В том же ДжаваСкрипте, если знаешь, такой вызов функции вполне легален:


ВВ>А ведь выполнение до функции Foo еще не дошло. Хотя в том же Руби такое уже не прокатит.

ВВ>В ДжаваСкрипте еще до выполнения объявлении функций вида function statement известны. А вот function expression, конечно, полностью динамические.

Не знал, спасибо за ликбез. Я думал, что function f() {...} это полный аналог f = function() {...}.

ВВ>Но вопрос не этом.

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

Да взаимоисключения нет. Просто по факту, кроме вот этого function, никакой статики нет.

T>>и var x = 1 и x = 1 одинаково видны при разборе дерева и одинаково возымеют какой-то эффект только при выполнении.


ВВ>Какой эффект при исполнении должно возыметь:


ВВ>
ВВ>var x;
ВВ>


Это синоним к var x = undefined со всеми последствиями.

ВВ>>>Гм, неужели ты не знаешь тот же ДжаваСкрипт? Это объясняет некоторое недопонимание. Все примеры, которые я приводил, это валидный джава-скрипт, с помощью которого я пытался иллюстрировать свою мысль.

T>>Javascript вроде знаю. Что примеры — валидный жаваскрипт понимаю. Мысль (попытку разделить определения на явные и неявные) не понимаю.
ВВ>Тогда почему ты написал, что не знаешь динамические языки с явной декларацией переменных?

declaration и definition, как я уже писал раньше это разные вещи.

Самое близкое к явной декларации что я знаю это var x; но это на самом деле определение x = undefined, не только декларация. Вы знаете примеры, когда имя декларируется, но значение ему не присваивается?

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

T>>Разница с текущим жаваскриптом предлагается в том, чтобы заставить перед каждым именем писать var, таким образом, исключив возможность в функциях менять глобальные переменные? Потому что кроме этого всё так и есть прямо сейчас. Даже "просто ключевое слово var и имя".


ВВ>А причем тут глобальные переменные? Мне упорно кажется, что у тебя неправильное понимание чего-то. К изменению глобальных переменных var никакого отношения не имеет. Ты можешь их спокойно менять.


Перефразирую, "исключив таким образом возможность в функциях объявлять глобальные переменные"? Или это тоже решается с помощью base?
То есть разница с текущим жаваскриптом предлагается в том, чтобы просто заставить всегда писать var перед объявлением имени? Может быть тогда лучше наоборот, заставить не писать var перед любым объявлением? В Python/Ruby именно так и сделано. Нормально получается, не сложно, не муторно, всё работает. Все кто пишут больше месяца на этих языках не задумываются о таких вещах.

T>>function f() { var x; return x; }; f()

T>>undefined
ВВ>Что значит этот пример? Ты объявил переменную, не присвоил значение (ее значение undefined). Что удивляет?

Первое обращение должно либо представлять собой присвоение, либо просто содержать ключевое слово var и имя.

кроме слова "должно" уже всё так и есть, оно работает.
Re[8]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 22:07
Оценка:
Здравствуйте, Temoto, Вы писали:

T>Да взаимоисключения нет. Просто по факту, кроме вот этого function, никакой статики нет.


А вот и есть. Это var. Все объявления переменных через var тоже известны еще в компайл-тайм.

ВВ>>
ВВ>>var x;
ВВ>>

T>Это синоним к var x = undefined со всеми последствиями.

С какими? Да это вообще неважно, синоним или нет. Undefined там потому что это единственный способ выразить отсутствие значения. Как его еще выражать? Не ошибку же генерировать. Короче:

//Явно объявили имя и используем
var x = 0; 
x += 1;

//Имя не объявляли и используем
x = 0;
x += 1;


Собственно, вот о чем я. Все просто.

ВВ>>>>Гм, неужели ты не знаешь тот же ДжаваСкрипт? Это объясняет некоторое недопонимание. Все примеры, которые я приводил, это валидный джава-скрипт, с помощью которого я пытался иллюстрировать свою мысль.

T>>>Javascript вроде знаю. Что примеры — валидный жаваскрипт понимаю. Мысль (попытку разделить определения на явные и неявные) не понимаю.
ВВ>>Тогда почему ты написал, что не знаешь динамические языки с явной декларацией переменных?

T>declaration и definition, как я уже писал раньше это разные вещи.


Хочешь сказать, что var x — это не declaration? Но ведь даже в глобальном скопе семантика этого выражения иная. При "неявном" (ну не могу я придумать другой термин) объявлении вообще можно сделать так:

x = 1;
delete x;
alert(x); //error


T>Самое близкое к явной декларации что я знаю это var x; но это на самом деле определение x = undefined, не только декларация. Вы знаете примеры, когда имя декларируется, но значение ему не присваивается?


Такое невозможно в динамическом языке Вернее, наверное, сделать можно, но смысл Единственный вариант — генерировать исключение, если значение не было присвоено явно. Но неясно зачем это делать.
Поэтому декларация + присвоение получается by design — мы переменную в карту загнали, все равно там должно быть хоть какое-то значение, ну чисто физически.
Хотя это даже и не важно. Пусть будет обязательное декларация+присвоение.
Мне интересно, насколько напрягает обязательность декларации. Насколько сильно она противоречит идеологии динамических языков.

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


Даже не знаю как объяснить. Явное — это когда перед тем как обращаться к некоему значению по имени, данное имя было изначально объявлено с помощью некоего ключевого слова (например, var). Неявное — когда мы сразу оперируем со значением по имени, которое до этого с помощью var не вводилось.

T>>>Разница с текущим жаваскриптом предлагается в том, чтобы заставить перед каждым именем писать var, таким образом, исключив возможность в функциях менять глобальные переменные? Потому что кроме этого всё так и есть прямо сейчас. Даже "просто ключевое слово var и имя".

ВВ>>А причем тут глобальные переменные? Мне упорно кажется, что у тебя неправильное понимание чего-то. К изменению глобальных переменных var никакого отношения не имеет. Ты можешь их спокойно менять.
T>Перефразирую, "исключив таким образом возможность в функциях объявлять глобальные переменные"? Или это тоже решается с помощью base?

Да, это правильно. Через base не решается. Но мне вообще кажется, что это фича Я так и не понял, зачем из функции объявлять глобальные переменные На мой взгляд это сайд-эффект. При создании своего интерпретатора и написании резолвинга имен у меня точно такой же эффект получился как бы by design. Есть у меня подозрение, что в том же джаваскрипте "ноги" примерно оттуда же растут.

T>То есть разница с текущим жаваскриптом предлагается в том, чтобы просто заставить всегда писать var перед объявлением имени? Может быть тогда лучше наоборот, заставить не писать var перед любым объявлением?


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

1. В компайл-тайме про переменные ничего неизвестно, где они объявляются и пр. Невозможно сделать оптимальную карту локалей (например, приходится делать ассоциативный массив, который меняется в рантайме, вместо индексированного массива и доступа по индексу). Последнее на ряде задач очень нехреново поднимает перформанс.
2. А иногда и программисту удобнее. Защита от опечаток. Если неправильно набрал какое-то имя, то получится ошибка, а не странный эффект, что ты получил какое-то значение, но совсем не то, которое ожидалось.

T>В Python/Ruby именно так и сделано. Нормально получается, не сложно, не муторно, всё работает. Все кто пишут больше месяца на этих языках не задумываются о таких вещах.


Я понимаю. Я рассматриваю возможность введения, скажем так, некоторых статических аннотаций.

T>

Первое обращение должно либо представлять собой присвоение, либо просто содержать ключевое слово var и имя.

кроме слова "должно" уже всё так и есть, оно работает.


Я знаю. Все изменение заключается как раз в слове "должно".
Re[9]: Динамические языки и переменные
От: Temoto  
Дата: 05.03.10 23:10
Оценка:
T>>Да взаимоисключения нет. Просто по факту, кроме вот этого function, никакой статики нет.
ВВ>А вот и есть. Это var. Все объявления переменных через var тоже известны еще в компайл-тайм.

То есть по аналогии с function, должен работать такой код:

print(x); // я тестил на rhino, там есть print
var x = 1;

И он не работает. Я понимаю это как 'var' не статический.

ВВ>Собственно, вот о чем я. Все просто.


Ну мы опять возвращаемся к глобальным переменным. Вы глобальные определения хотите назвать неявными. Я читаю x = 0 как явное определение глобальной переменной.
Есть ещё граничный случай, вы его приводили выше

// в глобальном скопе
var x = 1;
(function f() { x = 2; })()

То есть функция неявно меняет переменную в глобальном скопе. И это особенность жаваскрипта, а не динамических языков в целом. Но это можно так конкретно и назвать — неявное [пере]определение глобальных переменных. В Python/Ruby подобный код объявит новое локальное имя.

ВВ>>>Тогда почему ты написал, что не знаешь динамические языки с явной декларацией переменных?

T>>declaration и definition, как я уже писал раньше это разные вещи.
ВВ>Хочешь сказать, что var x — это не declaration? Но ведь даже в глобальном скопе семантика этого выражения иная. При "неявном" (ну не могу я придумать другой термин) объявлении вообще можно сделать так:

Хакей, я имел в виду декларацию без определения. В жаваскрипте var x; гарантировано определяет значение x. В си int x; не гарантирует значения x и использование этой переменной перед её определением даст варнинг.

T>>Самое близкое к явной декларации что я знаю это var x; но это на самом деле определение x = undefined, не только декларация. Вы знаете примеры, когда имя декларируется, но значение ему не присваивается?

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

Обязательность декларации без определения очень сильно напрягает. Это ублажение компилятора.
Обязательность декларации с определением это где-то на уровне common sense. Без этого должен работать бредовый код unknown_name + 2 == 2.

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

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


ВВ>Даже не знаю как объяснить. Явное — это когда перед тем как обращаться к некоему значению по имени, данное имя было изначально объявлено с помощью некоего ключевого слова (например, var). Неявное — когда мы сразу оперируем со значением по имени, которое до этого с помощью var не вводилось.


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

ВВ>>>А причем тут глобальные переменные? Мне упорно кажется, что у тебя неправильное понимание чего-то. К изменению глобальных переменных var никакого отношения не имеет. Ты можешь их спокойно менять.

T>>Перефразирую, "исключив таким образом возможность в функциях объявлять глобальные переменные"? Или это тоже решается с помощью base?

ВВ>Да, это правильно. Через base не решается. Но мне вообще кажется, что это фича Я так и не понял, зачем из функции объявлять глобальные переменные На мой взгляд это сайд-эффект. При создании своего интерпретатора и написании резолвинга имен у меня точно такой же эффект получился как бы by design. Есть у меня подозрение, что в том же джаваскрипте "ноги" примерно оттуда же растут.


Если говорить о красивости решений, то меня очень напрягает возможность переопределять глобальные переменные из функций. Вообще, неявный доступ на запись к глобальным переменным (например, global_obj.attr = 2) это зло, потому что ведёт к трудноуловимым ошибкам.

T>>То есть разница с текущим жаваскриптом предлагается в том, чтобы просто заставить всегда писать var перед объявлением имени? Может быть тогда лучше наоборот, заставить не писать var перед любым объявлением?


ВВ>В принципе это логично. Или всегда писать, или всегда не писать. Вариант всегда не писать на мой взгляд для динамического языка и для самой природы переменной в динамическом языке более естественный. Но тут есть две проблемы:


ВВ>1. В компайл-тайме про переменные ничего неизвестно, где они объявляются и пр. Невозможно сделать оптимальную карту локалей (например, приходится делать ассоциативный массив, который меняется в рантайме, вместо индексированного массива и доступа по индексу). Последнее на ряде задач очень нехреново поднимает перформанс.


На мой взгляд, эти проблемы в целом характерны для динамических языков. Обособляется определение переменной с помощью ключевого слова или нет — одинаково мало известно во время компиляции.

ВВ>2. А иногда и программисту удобнее. Защита от опечаток. Если неправильно набрал какое-то имя, то получится ошибка, а не странный эффект, что ты получил какое-то значение, но совсем не то, которое ожидалось.


Без комментариев.

T>>В Python/Ruby именно так и сделано. Нормально получается, не сложно, не муторно, всё работает. Все кто пишут больше месяца на этих языках не задумываются о таких вещах.

ВВ>Я понимаю. Я рассматриваю возможность введения, скажем так, некоторых статических аннотаций.

Я уже советовал почитать ссылку выше. Так вот там есть такой кусочек:

Michael Salib attempted to solve this problem with StarKiller[1]. The compiler manages type inference by collecting more information than usual and using the CTA algorithm.

[1] http://www.salib.com/writings/thesis/thesis.pdf

Очень интересно, советую.

ВВ> Первое обращение должно либо представлять собой присвоение, либо просто содержать ключевое слово var и имя.

T> кроме слова "должно" уже всё так и есть, оно работает.
ВВ> Я знаю. Все изменение заключается как раз в слове "должно".

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

Но даже если новый язык с обязательным ключевым словом, я уверен, что писать лишние 4 символа будет не самая большая проблема этого языка.
Re[10]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 23:30
Оценка:
Здравствуйте, Temoto, Вы писали:

T>>>Да взаимоисключения нет. Просто по факту, кроме вот этого function, никакой статики нет.

ВВ>>А вот и есть. Это var. Все объявления переменных через var тоже известны еще в компайл-тайм.

T>То есть по аналогии с function, должен работать такой код:


T>print(x); // я тестил на rhino, там есть print

T>var x = 1;

T>И он не работает. Я понимаю это как 'var' не статический.


Ты путаешь разные вещи. Объявление и присвоение. Присвоение, ес-но, динамическое и не будет сделано, пока поток исполнения не дойдет до этой инструкции. Это во всех языках так.
Присвоение не статическое, но объявление статическое. Сравни:

alert(x); //я тестил это в MSIE :))
x = 1;


Результат:

Ошибка: 'x' - определение отсутствует


И второй вариант:

alert(x);
var x;


Результат:
Все прекрасно работает.

ВВ>>Собственно, вот о чем я. Все просто.


T>То есть функция неявно меняет переменную в глобальном скопе. И это особенность жаваскрипта, а не динамических языков в целом. Но это можно так конкретно и назвать — неявное [пере]определение глобальных переменных. В Python/Ruby подобный код объявит новое локальное имя.


Логично. Ведь в Python/Ruby нет var, поэтому если бы они вели себя как ДжаваСкрипт там бы локальные имена вообще ввести было нельзя Ну кроме шуток, в подобной ситуации всегда происходило бы обращение именно к глобальному имени, а не локальному.
В ДжаваСкрипте, благодаря var-y, ты можешь выбирать:

var x = 1;

function Foo()
{
  x = 2; //глобальную поменяли
}


и

var x = 1;

function Foo()
{
  var x = 2; //ввели локальную
}



ВВ>>>>Тогда почему ты написал, что не знаешь динамические языки с явной декларацией переменных?

T>>>declaration и definition, как я уже писал раньше это разные вещи.
ВВ>>Хочешь сказать, что var x — это не declaration? Но ведь даже в глобальном скопе семантика этого выражения иная. При "неявном" (ну не могу я придумать другой термин) объявлении вообще можно сделать так:

T>Обязательность декларации без определения очень сильно напрягает. Это ублажение компилятора.

T>Обязательность декларации с определением это где-то на уровне common sense. Без этого должен работать бредовый код unknown_name + 2 == 2.

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

//так можно
var x; 
x = 2;

//так тоже можно
var x = 2;

//а так уже нет
x = 2;


А unknown_name + 2 == 2 мне кажется вообще никогда не должен работать

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


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

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

ВВ>>Даже не знаю как объяснить. Явное — это когда перед тем как обращаться к некоему значению по имени, данное имя было изначально объявлено с помощью некоего ключевого слова (например, var). Неявное — когда мы сразу оперируем со значением по имени, которое до этого с помощью var не вводилось.
T>То есть без ключевого слова это уже неявное определение? Тогда в Python/Ruby/Erlang все определения неявные?

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

ВВ>>>>А причем тут глобальные переменные? Мне упорно кажется, что у тебя неправильное понимание чего-то. К изменению глобальных переменных var никакого отношения не имеет. Ты можешь их спокойно менять.

T>>>Перефразирую, "исключив таким образом возможность в функциях объявлять глобальные переменные"? Или это тоже решается с помощью base?

ВВ>>Да, это правильно. Через base не решается. Но мне вообще кажется, что это фича Я так и не понял, зачем из функции объявлять глобальные переменные На мой взгляд это сайд-эффект. При создании своего интерпретатора и написании резолвинга имен у меня точно такой же эффект получился как бы by design. Есть у меня подозрение, что в том же джаваскрипте "ноги" примерно оттуда же растут.

T>Если говорить о красивости решений, то меня очень напрягает возможность переопределять глобальные переменные из функций. Вообще, неявный доступ на запись к глобальным переменным (например, global_obj.attr = 2) это зло, потому что ведёт к трудноуловимым ошибкам.

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

T>Я уже советовал почитать ссылку выше. Так вот там есть такой кусочек:

T>

Michael Salib attempted to solve this problem with StarKiller[1]. The compiler manages type inference by collecting more information than usual and using the CTA algorithm.

T>[1] http://www.salib.com/writings/thesis/thesis.pdf

Я читал. Интересно. Но просветления пока нет.

ВВ>> Первое обращение должно либо представлять собой присвоение, либо просто содержать ключевое слово var и имя.

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

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

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


Понятно.
Re[10]: Динамические языки и переменные
От: Воронков Василий Россия  
Дата: 05.03.10 23:41
Оценка:
Здравствуйте, Temoto, Вы писали:

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
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.