Чому оператор призначення присвоює ліву частину?


47

Я почав викладати друга програмуванню зовсім недавно (ми використовуємо Python), і коли ми почали обговорювати створення змінних та оператора призначення, вона запитала, чому значення праворуч присвоюється імені зліва, а не навпаки .

Раніше я не надто замислювався над цим, бо це мені здавалося природним, але вона сказала, що ліво-праворуч їй здається більш природним, оскільки саме так більшість із нас читає природні мови.

Я подумав над цим і дійшов висновку, що це робить код набагато простішим для читання, оскільки імена, призначені (які програмісту потрібно буде повторно використовувати), легко видно, вирівняні зліва.

aligned = 2
on = 'foo' + 'bar' + 'foobar'
the = 5.0 / 2
left = 2 + 5

На відміну від:

2 = aligned 
'foo' + 'bar' + 'foobar' = on
5.0 / 2 = the 
2 + 5 = right 

# What were the names again...?

Тепер мені цікаво, чи є для цього стандарту й інші причини. Чи є за нею історія? Або є якась технічна причина, чому це хороший варіант (я не знаю багато про компілятори)? А чи є мови програмування, які призначаються праворуч?


15
R можна призначити праворуч ( value -> variable).
Ти

Можливо, це пов’язано з поганими назвами змінних? Як щодо "numAligned is 2" та "chickensLeft - 2 + 5"?
робота

18
Ім'я твого друга ... Йода?
Адріан

1
Якщо вона почне комбінувати з цього приводу, мені цікаво, що вона буде робити, коли побачить C ++ & co.
BlackBear

3
Лише побічна примітка: Академія Хана має кілька уроків з Python для початківців програмістів: khanacademy.org/#computer-science, а Google має кілька для більш просунутих: code.google.com/edu/languages/google-python-class/set- up.html
линдонська лисиця

Відповіді:


56

Дітто @paxdiablo. Мови раннього програмування були написані математиками - насправді всі вони були. У математиці за її власним принципом - читання зліва направо - це має сенс у тому, як це працює.

x = 2y - 4.

У математиці ви б сказали так: Нехай x дорівнює 2y -4.

Також навіть в алгебрі ти це робиш. Розв'язуючи рівняння для змінної, ви ізолюєте змінну, яку ви розв'язуєте, на ліву сторону. тобто y = mx + b;

Крім того, коли ціла сім'я мов - наприклад, сім'я C - має певний синтаксис, змінити її дорожче.


19
@FarmBoy: в математиці завдання і рівність - це одне і те ж, оскільки у формулі немає послідовності, як це є в комп'ютерах. (дорівнює b і в той же час b дорівнює a)
Петруза

1
@FB за винятком деяких функціональних мов одного призначення, наприклад, Erlang. Присвоєння та забезпечення рівності такі ж, як у математиці
Peer Stritzinger

18
@Petruza Ні, математичне завдання та рівність - це не одне і те ж. Якщо я скажу "Нехай x = 2y - 3", це відрізняється від "Таким чином, x = 2y - 3". Я математику, як правило, контекст їх диференціює. Оскільки коментар, який мене сприйняв, був настільки загальновизнаний, я зазначу, що в мене є доктор наук. в математиці я майже впевнений у цьому.
Ерік Вілсон

2
Я не знаю математики десь поруч із доктором наук, зазначаю, що оскільки немає послідовності, немає порядку виконання математики як у завданні, так і в рівності, на відміну від програмування, в якому обидві сторони завдання можуть бути в якийсь момент часу різні, і вони в кінці іншого періоду рівні. Але в математиці в такому завданні, як let a be...немає часу, обидві сторони завдання є рівними, тому завдання - це насправді рівність, не дивно, чому обидва використовують один і той же знак:=
Петруза

5
@Petruzza - але є послідовність. Математичні документи пишуться від початку до кінця, так само, як і будь-який інший документ. Якщо я стверджую x = 1в першій главі, але запевняю x = 2в другій главі, це не якесь жахливе протиріччя - кожне твердження застосовується лише в певному контексті. Різниця в імперативному програмуванні частково полягає у усуненні бар'єру (нам не потрібна зміна контексту), а частково - щодо впровадження та корисності.
Steve314

26

BASIC, одна з найдавніших комп'ютерних мов мала "належну" форму:

10 LET AREA = HEIGHT * WIDTH

який відповідає математичному умові визначення заданої змінної, наприклад "Нехай H - висота об'єкта".

COBOLтакож був подібний із своїм COMPUTEтвердженням. Як і для багатьох способів вчинити, це може бути просто довільним рішенням, яке виносилося на багатьох мовах.


7
Я вважаю, що ця форма є більш природною, коли програмні рядки розглядаються як "заяви" на відміну від "операцій". Як і в, I declare that X must equal THISзамість більш лінійногоEvaluate THIS and store it in X
voithos

Зачекайте, BASIC була "ранньою" комп'ютерною мовою?
Алекс Фейнман

2
@ Алекс Враховуючи, що це страждає від 1960-х, я б сказав, що це досить рано.
Бен Річардс

1
З іншого боку, в COBOL ви можете писати MULTIPLY HEIGHT BY WIDTH GIVING AREA, тому змінна, яка отримує результат, знаходиться в самій правій частині заяви.
користувач281377

25

Насправді є мова програмування, яка призначається праворуч: TI-BASIC ! Мало того, але він також не використовує '=' як оператор призначення, а скоріше використовує стрілку, відому як оператор "STO".

приклади:

5→A
(A + 3)→B
(A - B)→C

У наведеному вище прикладі три змінних оголошуються та надаються значення. A було б 5, B - 8, а C - -3. Перша декларація / призначення може бути прочитана "зберігати 5 як A".

Щодо того, чому TI-BASIC використовує таку систему для призначення, я приписую це тому, що це мова програмування для калькулятора. Оператор "STO" на калькуляторах TI найчастіше використовувався в звичайних операціях калькулятора після обчислення числа. Якщо це було число, яке користувач хотів запам’ятати, вони натиснули б кнопку «STO», а какулятор запропонує їм ім’я (автоматично замикаючи альфа-замок, щоб натискання клавіш створювало літери замість цифр):

Sin(7 + Cos(3))
                    -.26979276
Ans→{variable name}
                    -.26979276

і користувач міг назвати змінну, що б не обрав. Увімкнувши альфа-блокування, введіть ім'я, потім натисніть "STO", і натискання клавіші "Ans" було б занадто громіздким для звичайних операцій. Оскільки всі функції калькулятора доступні в TI-BASIC, жодних інших операторів призначення не додано, оскільки "STO" виконував ту саму задачу, хоч і назад, порівняно з більшістю інших мов.

(Анекдот: TI-BASIC був однією з перших мов, які я навчився, тому коли я, коли я вперше вивчав Java в коледжі, я відчував, ніби приєднання до Лівого було незвичним та "назад"!)


+1 Я це зовсім забув! TI Basic теж був моєю першою мовою, але я не пам'ятаю цієї деталі.
barjak

Насправді оператор STO ближче до того, як працює машина і як діє будь-яка мова. Спочатку значення обчислюється, а потім зберігається в пам'яті.
Kratz

15

Евристичний 1: Коли ви стикаєтесь з більш ніж одним із можливих способів зробити щось під час створення мови, виберіть найпоширеніший, найінтуїтивніший, інакше у вас вийде Perl +.

Тепер, як це більш природно (принаймні, для англійської мови)? Давайте подивимось, як ми пишемо / говоримо речі англійською мовою:

Зараз Стівену 10 років (на відміну від 10 років Стівену зараз). Я важу понад 190 фунтів (на відміну від понад 190 фунтів я важу).

У коді:

steven = 10
i > 190

Наступне також звучить більш природно:

"Якщо Марії 18 років, то вона може мати цукерку". "Якщо я молодший за 21 рік, то я попрошу брата, щоб він був мене текілою".

if (mary == 18) { ... }
if (i < 21) { ... }

ніж:

"Якщо 18 років Марія - це ..." "Якщо 21 рік більше мого віку ..."

Тепер код:

if (18 == mary) { ... }
if (21 > i) { ... }

Зауважте, що це не природно ні для програмістів, ні для англійських. Речення звучать як yoda-speak, а код називається yoda-condition. Вони можуть бути корисними для C ++, але я впевнений, що більшість людей погодиться: якби компілятор міг би зробити важкий підйом і полегшити потребу в умовах йоди, життя було б трохи простіше.

Звичайно, можна звикнути до чого завгодно. Наприклад, число 81 записується як:

Вісімдесят один (англійська) Вісімдесят і один (іспанський) Один і вісімдесят (німецький).

Нарешті, є 4! = 24 дійсних способу сказати "зелене яблуко лежить на столі" російською мовою - порядок (майже) не має значення, за винятком того, що "на" повинен поєднуватися зі "столом". Отже, якщо ви є носієм російської мови (наприклад), то вам може бути все одно, чи пишете ви, a = 10чи 10 = aтому, що обидва здаються однаково природними.

Хоча мовознавство є захоплюючим предметом, я ніколи формально його не вивчав і не знаю, що багато мов. Будемо сподіватися, що я подав достатньо зустрічних прикладів.


4
... а французькою мовою 81 кажуть як "чотири рази двадцять один" ... :)
Мартін Сойка

1
@Martin, я вважаю, що данська дуже схожа.
CVn

7
@Martin Це дійсно дивно, тому що чотири рази двадцять один - 84.
Пітер Олсон

6
@ Peeter: ви неправильно зробили ваші круглі дужки, це(four times twenty) one
SingleNegationElimination

4
@Job: Читаючи твій "Якщо 18 років Марія - це ...", мені неминуче нагадали Йоди, які сказали: "Коли ви досягнете дев'ятсот років, виглядайте так добре, як ні, так?" у відповідь на джедаїв :-)
joriki

11

Це розпочалося з FORTRAN у 1950-х роках. Де FORTRAN було абревіатурою FORmula TRANSlation - формули, про які йдеться, були простими алгебраїчними рівняннями, які за умовою завжди присвоюються зліва.

З іншого боку, його близький сучасний COBOL мав бути як англійський і призначатися праворуч (здебільшого!).

MOVE 1 TO COUNTER.
ADD +1 TO LINE-CNT.
MULTIPLY QTY BY PRICE GIVING ITEM-PRICE.

Я думаю, що це найкращий приклад, оскільки він ідеально ілюструє контекст мовою, де він читається для загального англійського, хто говорить, але має правильне призначення. Я кажу, що це важливо через те, що велика кількість людей, які говорять англійською мовою, читатимуть лише зліва направо, щоб завдання отримало сенс, що абсолютно не відповідає дійсності.
Джошуа Хеджес

5

Що ж, як зазначав @ diceguyd30, є обидва позначення.

  • <Identifier> = <Value>означає "нехай ідентифікатор буде значенням ". Або розгорнути це: Визначте (або перезначте) змінну Ідентифікатор до значення .
  • <Value> -> <Identifier>означає "зберігати значення до ідентифікатора ". Або розширити це: введіть значення в місце, визначене ідентифікатором .

Звичайно, в цілому Ідентифікатор насправді може бути будь-яким значенням L.

Перший підхід шанує абстрактне поняття змінних, другий підхід стосується фактичного зберігання.

Зауважте, що перший підхід також поширений у мовах, які не мають призначення. Також зазначу, що визначення змінного і призначення щодо близький <Type> <Identifier> = <Value>проти <Identifier> = <Value>.


3

Як уже згадувалося, досить добре всі ранні комп'ютерні мови працювали саме так. Наприклад, FORTRAN, який прийшов за багато років до основи.

Насправді має великий сенс мати присвоєну змінну зліва від виразу призначення. У деяких мовах у вас може бути декілька різних перевантажених процедур із ІМИ ІМ’ЯМ, повертаючи різні типи результатів. Дозволяючи компілятору спочатку побачити тип призначеної змінної, він знає, яку перевантажену процедуру викликати або який неявний кидок для генерації при перетворенні з (наприклад) цілого числа в плаваючу. Це трохи спрощене пояснення, але, сподіваємось, ви зрозумієте цю ідею.


2
Я розумію ваше пояснення, але чи не міг компілятор просто заглянути до кінця висловлювання?
voithos

Це може полегшити лексеру в сучасних мовах, але скільки мов програмування навіть підтримують названі методи, не кажучи вже про перевантаження, коли такий синтаксис був новим?
CVn

2
Привіт @voithos. Так - компілятор міг би заздалегідь, але це, мабуть, було б неприйнятним рівнем складності в перші дні написання компілятора - що часто було кодованим вручну асемблером! Я думаю, що розміщення призначеної змінної зліва - це прагматичний вибір: і людині, і машині простіше розібратися.
Дейв Джевелл

Я думаю, що було б тривіально, щоб завдання було присвоєно праворуч. Коли вираз, як 3 + 4 == 6 + 7, обидві сторони оцінюються перед оператором, оскільки мова визначається рекурсивно. Елемент мови 'змінний = вираз', ​​легко може бути змінений на 'izraz = змінна'. Від того, чи це спричинить неоднозначні ситуації, залежить від решти мови.
Kratz

@Kratz - це, безумовно, стосується компіляторів зараз, але, можливо, виникла незначна проблема для дуже старих інтерпретованих мов, які працювали з токенізованим джерелом. OTOH, що, можливо, віддало перевагу змінній праворуч, а не змінній ліворуч.
Steve314

3

Це може бути залишком алгоритмів раннього розбору. Пам’ятайте, що LR-синтаксис був винайдений лише у 1965 році, і цілком можливо, що у парляторів LL виникли проблеми (в межах часових та просторових обмежень машин на той час), навпаки. Поміркуйте:

identifier = function();
function();

Ці два чітко розмежовані від другої лексеми. З іншого боку,

function() = identifier;
function();

Не смішно. Це погіршується, коли ви починаєте вкладати вирази призначення.

function(prev_identifier = expression) = identifier;
function(prev_identifier = expression);

Звичайно, простіше розмежувати машини також означає, що легше розлучати людей. Іншим простим прикладом може бути пошук ініціалізації будь-якого даного ідентифікатора.

identifier1 = expressionOfAnArbitraryLength;
identifier2 = expressionOfAReallyReallyReallyArbitraryLength;
identifier3 = expression;
identifier4 = AlongLineExpressionWithAFunctionCallWithAssignment(
    identifier = expr);

Легко, просто дивіться лівою стороною вгору. Правий бік, з іншого боку

expressionOfAnArbitraryLength = identifier1;
expressionOfAReallyReallyReallyArbitraryLength = identifier2;
expression = identifier3;
AlongLineExpressionWithAFunctionCallWithAssignment(expr = identifier
    ) = identifier4;

Особливо, коли ви не можете grepпробивати картки, набагато складніше знайти потрібний ідентифікатор.


Саме той момент, про який я думав, так.
voithos

2

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

Якщо ви бачите =(або :=для паскальських діалектів), ви можете вимовити такі як is assigned the value, тоді природа зліва направо матиме сенс (адже ми також читаємо зліва направо на більшості мов). Оскільки мови програмування були переважно розроблені людьми, які читали зліва направо, конвенції дотримувалися.

Це тип залежності шляху . Я гадаю, якби комп’ютерне програмування були винайдені людьми, які розмовляли на івриті чи арабською мовою (чи якоюсь іншою мовою справа-наліво), тоді я підозрюю, що ми поставимо призначення праворуч.


Так, але я підозрюю, що текст у редакціях також буде правильним вирівнюванням ...
voithos

8
Не можна так узагальнювати мови мовлення. Вони залежать від місця призначення операнда.
quick_now

2
@quickly_now: правильно; насправді, більшість примітивних машинних мов (навіть сьогодні не складаються за сучасними мірками) навіть не мали призначення, оскільки зазвичай було лише один або два акумулятори загального призначення. Більшість операцій передбачає акумулятор як призначення, за винятком оптових кодів "store", в яких вказана лише адреса пам'яті, а не джерело (яке було акумулятором). Я дійсно не думаю, що це впливало на синтаксис призначення для мов, подібних до ALGOL.
Хав'єр

3
@Tangurena - Деякі мови асемблера мають призначення ліворуч. Не з коду опкоду (це зібраний об'єктний код), а зліва від списку аргументів для інструкції мнемонічна. Однак інші мають право призначення. У асемблері 68000 ви б написали mov.b #255, d0, наприклад, де d0реєстр потрібно призначити. Старіші асемблери мають лише один аргумент за інструкцію. У 6502 LDA #255(Load Accumulator) ви можете стверджувати, що значення Aліворуч, але воно також ліворуч STA wherever(Store Accumulator).
Steve314

2
І навіть Intel 4004 (4-бітний кінцевий предок сімейства 8086, з 8008 та 8080 між ними) був розроблений після призначення на мовах високого рівня. Якщо ви припускаєте, що серія 8086 є репрезентативною для того, що збирачі робили в 50-х роках і раніше, я дуже сумніваюся, що це правда.
Steve314

2

Для чого це коштує, більшість операторів , в COBOL читати зліва направо, так що обидва операнда були названі перший і останній пункт призначення, як: multiply salary by rate giving tax.

Однак я не хочу припускати, що твій студент може віддавати перевагу COBOL, побоюючись, що я буду (цілком справедливо) підписаний за те, щоб зробити такий низький, неповторний, несмачний коментар! :-)


1

вона сказала, що зліва направо їй здається більш природним, оскільки саме так більшість із нас читають природні мови.

Я думаю, що це помилка. З одного боку, ви можете сказати "призначити 10 на х" або "перемістити 10 на х". З іншого боку, ви можете сказати "встановити x на 10" або "x стає 10".

Іншими словами, залежно від вашого вибору дієслова, змінна, яка призначається, може бути, а може бути і не бути предметом, а може бути, а може і не бути зліва. Отже, "що є природним" якраз повністю залежить від вашого звичного вибору формулювання для подання завдання.


0

У псевдокоді оператор присвоєння дуже часто пишеться справа. Наприклад

2*sqrt(x)/(3+y) -> z

У калькуляторах Casio, навіть непрограмованих варіантах, змінна призначення також відображається праворуч

A+2B → C

У Forth змінна також є праворуч

expression variable !

У x86 синтаксис Intel має призначення ліворуч, але синтаксис GAS скасовує порядок, створюючи певну плутанину для багатьох людей, особливо щодо інструкцій щодо порядку параметрів, таких як віднімання чи порівняння. Ці інструкції однакові у двох різних діалектах

mov rax, rbx    ; Intel syntax
movq %rbx, %rax ; GAS syntax

Вони обидва переміщують значення в rbx до rax. Жодна інша мова монтажу, яку я знаю, не пише цільовий пункт праворуч, як GAS.

Деякі платформи ставлять вираз зліва і змінна справа:

MOVE expression TO variable      COBOL
expression → variable            TI-BASIC, Casio BASIC
expression -> variable           BETA, R
put expression into variable     LiveCode

https://en.wikipedia.org/wiki/Assignment_%28computer_science%29#Notation

Більшість мов присвоює значення ліворуч, одна з причин - це легке вирівнювання операторів, легше читати та розпізнавати змінну, оскільки позиції операторів присвоєння та змінних не будуть дико змінюватися в рядках, і це легше читати як "нехай змінна буде деяким значенням".

Однак деякі люди вважають за краще сказати "перемістити значення x на y" і написати змінну праворуч.


-1

Я думаю, що це дотримується логічного способу мислення.
Спочатку має бути поле (змінна), потім ви поміщаєте всередину в нього об'єкт (значення).
Ви не ставите об'єкт у повітря, а потім ставите коробку навколо нього.


2
так ти зробиш. у більшості мов права сторона оцінюється перед лівою.
Хав'єр

3
It''s "ведення на правій стороні дороги" тип речі. Це здається логічним, але тільки тому, що так, як ви це робили завжди. Всі вищі країни їздять ліворуч.
Джеймс Андерсон

1
@JamesAnderson вищих країн? : o
nawfal

Ви маєте рацію, це логічно лише для того, щоб система письма зліва направо як римська абетка, яку, напевно, використовує майже кожна мова програмування, якщо не вся.
Петруза
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.