ИМХО привязка переменной к другой переменной или выражению - очень распространенный сценарий в математике. Фактически, в начале, многие студенты думают, что оператор присваивания (=) является своего рода связыванием. Но в большинстве языков привязка не поддерживается как встроенная функция. В некоторых языках, таких как C #, привязка поддерживается в некоторых случаях при соблюдении некоторых условий.
Но IMHO реализовать это как встроенную функцию было так же просто, как изменить следующий код:
int a,b,sum;
sum := a + b;
a = 10;
b = 20;
a++;
к этому-
int a,b,sum;
a = 10;
sum = a + b;
b = 20;
sum = a + b;
a++;
sum = a + b;
Это означает размещение инструкции привязки в качестве присваиваний после каждой инструкции, изменяющей значения любой переменной, содержащейся в выражении справа. После этого будет выполнено обрезание избыточных инструкций (или оптимизация сборки после компиляции).
Итак, почему это не поддерживается изначально в большинстве языков. Особенно в С-семействе языков?
Обновить:
С разных точек зрения, я думаю, что я должен определить это предложенное «обязательное» более точно -
- Это один из способов связывания. Только сумма связана с a + b, а не наоборот.
- Область привязки является локальной.
- После того как привязка установлена, ее нельзя изменить. То есть, если сумма связана с a + b, сумма всегда будет a + b.
Надеюсь, идея прояснилась.
Обновление 2:
Я просто хотел эту функцию P # . Надеюсь, что это будет там в будущем.
источник
Ответы:
Вы путаете программирование с математикой. Даже функциональное программирование не является полностью математическим, хотя оно заимствует много идей и превращает их во что-то, что может быть выполнено и использовано для программирования. Императивное программирование (которое включает в себя большинство языков на основе C, примечательными исключениями являются JavaScript и более поздние дополнения к C #) почти не имеет ничего общего с математикой, так почему эти переменные должны вести себя как переменные в математике?
Вы должны учитывать, что это не всегда то, что вы хотите. Так много людей укушены замыканиями, созданными в циклах, в частности, потому что замыкания сохраняют переменную, а не копию ее значения в какой-то момент, то есть
for (i = 0; i < 10; i++) { var f = function() { return i; }; /* store f */ }
создают десять замыканий, которые возвращаются9
. Таким образом, вам нужно будет поддерживать оба способа, что означает удвоение затрат на «бюджет сложности» и еще одного оператора. Возможно также несовместимость между кодом, использующим это, и кодом, не использующим это, если система типов не является достаточно сложной (более сложная!).Кроме того, реализовать это очень сложно. Наивная реализация добавляет постоянные накладные расходы к каждому назначению, что может быстро накапливаться в императивных программах. Другие реализации могут задерживать обновления до тех пор, пока переменная не будет прочитана, но это значительно сложнее и все еще имеет издержки, даже когда переменная никогда не читается снова. Достаточно умный компилятор может оптимизировать оба, но достаточно умные компиляторы редки и требуют много усилий для создания (обратите внимание, что это не всегда так просто, как в вашем примере, особенно когда переменные имеют широкую область действия и многопоточность вступает в игру!).
Обратите внимание, что реактивное программирование в основном об этом (насколько я могу судить), поэтому оно существует. Это просто не так часто встречается в традиционных языках программирования. Бьюсь об заклад, некоторые из реализационных проблем, перечисленных в предыдущем абзаце, решены.
источник
Очень плохо подходит для большинства моделей программирования. Это будет представлять собой неконтролируемое действие на расстоянии, в котором можно уничтожить значение сотен или тысяч переменных и полей объекта, сделав одно присваивание.
источник
a
илиb
, вы должны рассмотреть его влияние на каждом месте , котороеsum
используется, и каждое место , которое вы читаетеsum
вы должны учитывать , чтоa
иb
делают. Для нетривиальных случаев это может осложниться, особенно если фактическое выражение, связанное с,sum
может измениться во время выполнения.Вы знаете, у меня есть это мучительное чувство, что реактивное программирование может быть круто в среде Web2.0. Почему чувство? Ну, у меня есть одна страница, которая в основном представляет собой таблицу, которая постоянно меняется в ответ на события onClick ячейки таблицы. А клики по ячейкам часто означают изменение класса всех ячеек в столбце или строке; и это означает бесконечные циклы getRefToDiv () и тому подобное, для поиска других связанных ячеек.
Итак, многие из написанных мной ~ 3000 строк JavaScript ничего не делают, кроме как находят объекты. Может быть, реактивное программирование может сделать все это за небольшую плату; и при огромном сокращении строк кода.
Что вы, ребята, думаете об этом? Да, я заметил, что моя таблица имеет много функций, похожих на электронные таблицы.
источник
Я думаю, что вы описываете, называется Spreadsheet:
... затем оценивая
B1
результаты 7.РЕДАКТИРОВАТЬ
Язык C иногда называют «портативной сборкой». Это императивный язык, тогда как электронные таблицы и т. Д. Являются декларативными языками. Говорить
B1=A1+1
и ожидатьB1
переоценки при измененииA1
определенно декларативно. Декларативные языки (из которых функциональные языки являются подмножеством) обычно считаются языками более высокого уровня, потому что они более далеки от того, как работает оборудование.С другой стороны, языки автоматизации, такие как релейная логика, обычно декларативны. Если вы напишете цепочку логики, которая говорит, что
output A = input B OR input C
она будет постоянно переоценивать это утверждение иA
может меняться всякий раз, когдаB
илиC
изменится. Другие языки автоматизации, такие как функциональная блок-схема (с которой вы, возможно, знакомы, если вы использовали Simulink), также являются декларативными и выполняются постоянно.Некоторое (встроенное) оборудование автоматизации запрограммировано на C, и если это система реального времени, она, вероятно, имеет бесконечный цикл, который повторяет логику снова и снова, подобно тому, как выполняется лестничная логика. В этом случае внутри вашего основного цикла вы можете написать:
... и поскольку он выполняется постоянно, он становится декларативным.
A
будет постоянно переоцениваться.источник
C, C ++, Objective-C:
Блоки обеспечивают обязательную функцию, которую вы ищете.
В вашем примере:
Вы устанавливаете
sum
выражениеa + b
в контексте, гдеa
иb
существуют переменные. Вы можете сделать это точно с помощью «блока» (он же закрытие, лямбда-выражение) в C, C ++ или Objective-C с расширениями Apple (pdf):Это устанавливает
sum
в блок, который возвращает сумму a и b. Спецификатор__block
класса хранения указывает, чтоa
иb
может измениться. Учитывая вышесказанное, мы можем запустить следующий код:и получить вывод:
Единственная разница между использованием блока и «связыванием», которое вы предлагаете, заключается в пустой паре скобок
sum()
. Разница междуsum
иsum()
есть разница между выражением и результатом этого выражения. Обратите внимание, что, как и в случае с функциями, круглые скобки не обязательно должны быть пустыми - блоки могут принимать параметры так же, как функции.источник
C ++
Обновлено, чтобы быть универсальным. Параметризован для типов возврата и ввода. Может предоставлять любую двоичную операцию, удовлетворяющую параметризованным типам. Код вычисляет результат по требованию. Он пытается не пересчитать результаты, если ему это сойдет с рук. Уберите это, если это нежелательно (из-за побочных эффектов, потому что содержащиеся объекты большие, из-за чего-либо.)
источник