Страница 1 из 4

Оператор присваивания

СообщениеДобавлено: 23.10.2007 09:42:38
Bonart
Казалось бы, нет ничего лучше традиционного Паскалевского оператора присваивания. Однако прогресс на месте не стоит и к настоящему времени есть ряд хороших расширений.
1. Использование для совмещения определения переменных с инициализацией.
переменная[:тип] := выражение
Если тип опущен, то он выводится компилятором.
Так можно избегать громозких секций описания и определять локальные переменные прямо в ходе. Опасность - опечатка при переприсваивании с возможностью опустить тип ведет к описанию новой переменной, т.е. синтаксическая ошибка становится семантической, что не есть хорошо.
Поэтому для присваиваний, совмещенных с описаниями есть резон сделать указание типа обязательным.
2. Использование для определения констант.
константа[:тип] ::= выражение
Кто сказал, что константы обязаны вычисляться только во время компиляции?
Константы - это то, что нельзя переприсваивать, а не только то, что вычислено еще до выполнения.
Такая возможность (аналог const в C++) позволяет обнаруживать ошибки переприсваивания того, что по логике алгоритма не должно обновляться. Вдобавок такой оператор позволяет компилятору сильно оптимизировать код.
Для констант необязательность указания типа логична и целессобразна - их никто переприсваивать не будет.
Почему именно ::=? Во-первых не будет коллизиии с операцией сравнения, во-вторых это сочетание знаков в БНФ означает "определено как".
3. Использование структур в левой части оператора присваивания.
Например, вот пример с кортежем:
(i, x) := (1, 1)
Это позволяет сделать код более лаконичным и прозрачным, выделяя логически связанные присваивания, а также позволяет лучше оптимизировать (а то и распараллелить!) код - порядок присваивания элементов внутри структуры не определен.

СообщениеДобавлено: 23.10.2007 10:33:59
bw
> переменная[:тип] := выражение
Так я считаю лучше:
Код: Выделить всё
var переменная: тип = выражение;

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

> константа[:тип] ::= выражение
Код: Выделить всё
const константа: тип = выражение;


> Во-первых не будет коллизиии с операцией сравнения
Код: Выделить всё
if константа == 1 then ...


..bw

СообщениеДобавлено: 23.10.2007 11:14:54
Bonart
bw
bw писал(а):А почему у тебя тип в кв. скобках? Ты думаешь что его объявление не всегда нужно?

Думаю, да. Тип переменной=тип выражения инициализации. Его в большинстве случае видно невооруженным глазом.
В большинстве случаев это даст лаконичность без потери прозрачности.
bw писал(а):Так я считаю лучше:

А зачем var? Указание типа переменной - уже ясно видимый признак определения, а не переприсваивания.
bw писал(а): Во-первых не будет коллизиии с операцией сравнения

От двойного равенства меня тошнит ;) Да и в математике равенство принято обозначать одиночным знаком.

СообщениеДобавлено: 23.10.2007 12:40:30
bw
> А зачем var? Указание типа переменной - уже ясно видимый признак определения, а не переприсваивания.
У тебя вроде как указание типа не обязхательно :-). Так что не всегда будет понятно, что к чему, а с var однозночно ясно. Врядли использование var сильно снизит скорость написания кода, зато при отладке поможет сильно. Я бы даже ввел (наверное) оператор "del":
Код: Выделить всё
var I: Integer = 0;
...
del I;
...
WriteLn(I);  {компилятор матюгнется}


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

..bw

СообщениеДобавлено: 23.10.2007 12:53:04
alexs
bw писал(а):Если же начинает смущать то что объявление переменной в одном месте, а инициализация (и использование) намного дальше - значит пока разбивать метод на два или большее число методов

Золотые слова :-)

СообщениеДобавлено: 23.10.2007 13:24:28
Bonart
bw писал(а):У тебя вроде как указание типа не обязхательно

Ага :) Но цель-то в большей лаконичности. Если не хочется давать компилятору генерить определения из опечаток - то лучше сделать указание типа переменной обязательным.
bw писал(а):Я бы даже ввел (наверное) оператор "del"

Незачем. У нас уже есть операторные скобки - переменная видна только на том уровне где определена и ниже.
bw писал(а):Хотя с другой стороны я не поощраю функции таких размеров где жизненный цикл переменной не прозрачен.

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

СообщениеДобавлено: 23.10.2007 14:28:58
bw
> Самый наглядный пример - параметр цикла
С этим в соседнюю ветку, так что как пример не катит.

> то им даже память можно не выделять!
Ну :-). Ну будешь же ты динамически под каждый "байт" (переменную) выделять память. Это делается иначе, и ты знаешь как.

Все же я остаюсь против возможности объявления переменной в теле функции.

p.s. Мы сильно в оффтоп ушли, не думаешь :-) ? Я думаю пора отделить часть сообщений в тему "Переменные" или что-нибудь такоё.

..bw

СообщениеДобавлено: 23.10.2007 15:05:44
Bonart
bw писал(а):Ну будешь же ты динамически под каждый "байт" (переменную) выделять память. Это делается иначе, и ты знаешь как.

Знаю :)
Но экономия есть: если в одной из альтернатив нам нужна переменная x, а в другой - y, то при определении на уровне подпрограммы расход памяти будет sizeof x+sizeof y, а при определении на уровне блока - max(sizeof x,sizeof y) - если выделять память на стеке при входе в подпрограмму.
Но что меня в свое время поразило - в рекурсивных подпрограммах экономия памяти за счет локализации переменных на более низком, чем подпрограммы, уровне давала возможность расширить рабочий (без переполнекния стека) диапазон параметров в несколько раз.
Кстати, вот такая иллюстрация:
Код: Выделить всё
begin
  t ::= a
  a := b
  b := t
end;

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

СообщениеДобавлено: 24.10.2007 00:15:00
Deepthroat
Я тоже думаю, что хорошо бы указывать тип. Это позволит избежать ошибок. Например, так очень даже ничего:

Код: Выделить всё
begin
  var t: integer := a;
  a := b;
  b := t;
end;


Здесь t - целое, и это мы наем точно. Но что, если тип не указан, а мы где-то вверху ошиблись в типе? Тем более, что описание a находится не сверху, а где-то внутри кода, т.е. надо долго и упорно искать это описание. Да если там еще и тип не указан, то вообще вешайся - ищи описание переменных (всех - вдруг одна из трех-пяти-десяти имеет тип real!), через которые описана a. А каждая переменная описана х.з. где, да еще и не у каждой тип указан. Т.е. для определения типа всех переменных, через которые описана a, надо определить тип всех переменных, через которые описаны все переменные, через которые описана a.

Ну вы поняли, да? К чему ведет необязательность объявления типа...

СообщениеДобавлено: 24.10.2007 08:00:11
Bonart
Deepthroat писал(а): Например, так очень даже ничего:

Так - плохо.
Во-первых var - лишнее, т.к. явное указание типа уже признак определения, а не переприсваивания.
Во-вторых temp изменять никто не собирается, а значит это не переменная, а константа.
В-третьих, при изменении типов a и b придется менять и тип t, что в данном случае явно лишняя работа.
Deepthroat писал(а):Т.е. для определения типа всех переменных, через которые описана a, надо определить тип всех переменных, через которые описаны все переменные, через которые описана a.

Ну и что? Компилятор с этим справится быстрее чем мы с набиванием пары символов.

СообщениеДобавлено: 24.10.2007 08:25:21
alexs
А ещё лучше
Код: Выделить всё
Swap(A,B)

И всё - нет проблем - и налядность на уровне

СообщениеДобавлено: 24.10.2007 08:32:46
Bonart
alexs писал(а):А ещё лучше

А swap что такое?
Процедура, макрос, оператор?
Для всех ли типов работает?
Может ли подставляться в код или генерит дорогостоящий вызов?
Можно ли написать свой аналог этого SWAP и каков будет его исходный текст?
Я всего лишь проиллюстрировал преимущество объявления констант и необязательность указания типа.

СообщениеДобавлено: 24.10.2007 10:29:00
alexs
Для эелементарных типо в стандартных библиотеках есть - щас на вскидку не помню, для своих - просто переопредели макросом - и будет тебе счастье :-)

СообщениеДобавлено: 24.10.2007 10:31:54
Bonart
alexs писал(а):просто переопредели макросом

Макросом? В языке высокого уровня?
Лекарство хуже болезни получается. В худших традициях Си.
"И эти люди запрещают мне опускать тип переменной!"

СообщениеДобавлено: 24.10.2007 11:52:13
alexs
Bonart писал(а):Макросом? В языке высокого уровня?

Я под макросом подразумевал inline-функцию

а при обявлении перемнной её тип указывать надо! :-)