Mengapa operator penugasan menugaskan ke sisi kiri?

47

Saya mulai mengajar pemrograman teman baru-baru ini (kami menggunakan Python), dan ketika kami mulai membahas pembuatan variabel dan operator penugasan, ia bertanya mengapa nilai di sebelah kanan diberikan ke nama di sebelah kiri, dan bukan sebaliknya. .

Saya tidak terlalu memikirkannya sebelumnya, karena itu tampak alami bagi saya, tetapi dia mengatakan bahwa kiri-ke-kanan tampak lebih alami baginya, karena itulah sebagian besar dari kita membaca bahasa alami.

Saya memikirkannya, dan menyimpulkan bahwa itu membuat kode lebih mudah dibaca, karena nama-nama yang ditugaskan (yang perlu digunakan kembali oleh programmer) mudah terlihat, disejajarkan di sebelah kiri.

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

Sebagai lawan:

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

# What were the names again...?

Sekarang saya bertanya-tanya apakah ada alasan lain juga untuk standar ini. Apakah ada sejarah di baliknya? Atau ada beberapa alasan teknis mengapa ini merupakan opsi yang baik (saya tidak tahu banyak tentang kompiler)? Dan apakah ada bahasa pemrograman yang menetapkan ke sisi kanan?

voithos
sumber
15
R dapat menetapkan ke sisi kanan ( value -> variable).
Anda
Mungkin ini karena nama variabel yang buruk? Bagaimana dengan 'numAligned adalah 2` dan' chickensLeft adalah 2 + 5 '?
Pekerjaan
18
Apakah nama teman Anda ... Yoda?
Adrian
1
Jika dia mulai mengeluh tentang ini, saya ingin tahu apa yang akan dia lakukan ketika dia melihat C ++ & co.
BlackBear
3
Hanya catatan tambahan: Khan Academy memiliki beberapa pelajaran tentang Python untuk programmer pemula: khanacademy.org/#computer-science dan Google memiliki beberapa untuk lebih lanjut: code.google.com/edu/languages/google-python-class/set- up.html
lindon fox

Jawaban:

56

Ditto @paxdiablo. Bahasa pemrograman awal ditulis oleh matematikawan - sebenarnya semuanya. Dalam matematika, dengan prinsipnya sendiri - membaca dari kiri ke kanan - masuk akal dalam cara kerjanya.

x = 2thn - 4.

Dalam matematika, Anda akan mengatakan ini: Misalkan x sama dengan 2y -4.

Juga, bahkan dalam aljabar kamu melakukan ini. Saat Anda memecahkan persamaan untuk variabel, Anda mengisolasi variabel yang Anda pecahkan untuk sisi kiri. yaitu y = mx + b;

Selain itu, sekali seluruh keluarga bahasa - seperti keluarga C - memiliki sintaks tertentu, lebih mahal untuk berubah.

Jonathan Henson
sumber
19
@FarmBoy: dalam matematika, tugas dan kesetaraan adalah hal yang sama, karena tidak ada urutan dalam rumus seperti yang ada di komputer. (a sama dengan b dan pada saat yang sama b sama dengan a)
Petruza
1
@ FB kecuali dalam beberapa bahasa fungsional penugasan tunggal seperti misalnya Erlang. Penugasan dan Menjamin persamaan adalah sama seperti dalam matematika
Peer Stritzinger
18
@Petruza Tidak, dalam tugas matematika dan kesetaraan bukanlah hal yang sama. Jika saya mengatakan 'Biarkan x = 2y - 3' berbeda dari 'Jadi x = 2y - 3'. Saya berhitung, biasanya konteks membedakan mereka. Karena komentar yang membantah saya diakui secara universal, saya akan menyebutkan bahwa saya memiliki gelar Ph.D. dalam matematika, saya cukup yakin tentang ini.
Eric Wilson
2
Saya tidak tahu matematika di dekat PhD, apa yang saya nyatakan adalah bahwa karena tidak ada urutan, tidak ada urutan eksekusi dalam matematika baik dalam tugas atau dalam kesetaraan, tidak seperti pemrograman, di mana kedua sisi tugas dapat berbeda di beberapa titik waktu, dan mereka akhirnya sama di beberapa titik waktu lainnya. Namun dalam matematika, dalam penugasan seperti let a be...karena tidak ada waktu, kedua sisi penugasan sama juga, jadi penugasan ini sebenarnya adalah persamaan, tidak heran mengapa keduanya menggunakan tanda yang sama:=
Petruza
5
@Petruzza - tetapi ada adalah sequenciality. Dokumen matematika ditulis dari awal hingga akhir, sama seperti dokumen lainnya. Jika saya menegaskan x = 1dalam bab satu, tetapi menegaskan x = 2dalam bab dua, itu bukan kontradiksi yang mengerikan - setiap pernyataan hanya berlaku dalam konteks tertentu. Perbedaan dalam pemrograman imperatif sebagian adalah penghapusan penghalang (kita tidak perlu perubahan konteks), dan sebagian tentang implementasi dan kegunaan.
Steve314
26

BASIC, salah satu bahasa komputer paling awal memiliki bentuk "layak":

10 LET AREA = HEIGHT * WIDTH

yang cocok dengan pola pikir matematika menentukan variabel, seperti "Biarkan H menjadi ketinggian objek".

COBOLjuga mirip dengan COMPUTEpernyataannya. Seperti banyak cara melakukan sesuatu, itu mungkin hanya keputusan sewenang-wenang yang dilakukan melalui banyak bahasa.


sumber
7
Saya kira formulir ini lebih alami ketika baris program dianggap sebagai "pernyataan" yang bertentangan dengan "operasi." Seperti dalam,, I declare that X must equal THISbukannya yang lebih linierEvaluate THIS and store it in X
voithos
Tunggu, BASIC adalah bahasa komputer 'awal'?
Alex Feinman
2
@Alex Menimbang bahwa itu mulai dari tahun 1960-an, saya akan mengatakan itu cukup awal.
Ben Richards
1
Di sisi lain, di COBOL Anda bisa menulis MULTIPLY HEIGHT BY WIDTH GIVING AREA, jadi variabel yang mendapatkan hasilnya ada di sisi kanan pernyataan.
user281377
25

Sebenarnya, ada bahasa pemrograman yang ditugaskan ke sisi kanan: TI-BASIC ! Bukan hanya itu, tetapi juga tidak menggunakan '=' sebagai operator penugasan, melainkan menggunakan panah yang dikenal sebagai operator "STO".

contoh:

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

Dalam contoh di atas, tiga variabel dinyatakan dan diberi nilai. A akan menjadi 5, B akan menjadi 8, dan C akan menjadi -3. Deklarasi / penugasan pertama dapat dibaca 'store 5 as A'.

Mengenai mengapa TI-BASIC menggunakan sistem seperti itu untuk penugasan, saya mengaitkannya karena merupakan bahasa pemrograman untuk kalkulator. Operator "STO" pada kalkulator TI paling sering digunakan dalam operasi kalkulator normal setelah angka dihitung. Jika itu adalah angka yang ingin diingat pengguna, mereka akan menekan tombol "STO", dan caclulator akan meminta mereka untuk sebuah nama (secara otomatis menggunakan kunci alfa sehingga penekanan tombol menghasilkan huruf alih-alih angka):

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

dan pengguna dapat memberi nama variabel apa pun yang mereka pilih. Harus mengaktifkan kunci alfa, ketik nama, lalu tekan "STO", dan menekan tombol "Ans" akan terlalu rumit untuk operasi normal. Karena semua fungsi kalkulator tersedia dalam TI-BASIC, tidak ada operator penugasan lain yang ditambahkan ketika "STO" melakukan tugas yang sama, meskipun mundur jika dibandingkan dengan sebagian besar bahasa lainnya.

(Anekdot: TI-BASIC adalah salah satu bahasa pertama yang saya pelajari, jadi ketika saya ketika saya pertama kali belajar Java di perguruan tinggi saya merasa seolah-olah menugaskan ke KIRI itu tidak biasa dan 'mundur'!)

diceguyd30
sumber
+1 Saya benar-benar lupa itu! TI Basic juga merupakan bahasa pertama saya, tetapi saya tidak ingat detail ini.
barjak
Sebenarnya operator STO lebih dekat dengan cara kerja mesin, dan bagaimana bahasa sebenarnya beroperasi. Nilai pertama dihitung dan kemudian disimpan dalam memori.
Kratz
15

Heuristik 1: Ketika dihadapkan dengan lebih dari satu cara yang mungkin untuk melakukan sesuatu saat mendesain bahasa, pilih yang paling umum, paling intuitif, atau Anda akan berakhir dengan Perl +.

Sekarang, bagaimana itu lebih alami (setidaknya untuk penutur bahasa Inggris)? Mari kita lihat bagaimana kita menulis / mengatakan sesuatu dalam bahasa Inggris:

Steven sekarang berusia 10 tahun (berbeda dengan Steven yang berumur 10 tahun sekarang). Saya menimbang lebih dari 190 pound (berbeda dengan lebih dari 190 pound yang saya timbang).

Dalam kode:

steven = 10
i > 190

Berikut ini juga terdengar lebih alami:

"Jika Mary berusia 18 tahun, maka dia dapat memiliki permen". "Jika saya lebih muda dari 21 tahun, maka saya akan meminta saudara saya untuk tequila".

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

dari:

"Jika 18 tahun, Mary ..." "Jika 21 lebih besar dari usiaku ..."

Sekarang kodenya:

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

Perhatikan bahwa ini tidak alami baik bagi programmer maupun penutur bahasa Inggris. Kalimat-kalimatnya terdengar seperti berbicara yoda, dan kode itu dijuluki kondisi-yoda. Ini mungkin membantu dalam C ++, tetapi saya yakin kebanyakan orang akan setuju: jika seorang kompiler dapat melakukan pengangkatan berat dan mengurangi kebutuhan untuk kondisi yoda, hidup akan sedikit lebih mudah.

Tentu saja, orang bisa terbiasa dengan apa pun. Sebagai contoh, angka 81 ditulis sebagai:

Eighty One (Inggris) Eighty dan satu (Spanyol) One dan Eighty (Jerman).

Akhirnya, ada 4! = 24 cara sah untuk mengatakan "apel hijau terletak di atas meja" dalam bahasa Rusia - urutan (hampir) tidak masalah, kecuali bahwa 'on' harus datang bersama dengan 'table'. Jadi, jika Anda adalah penutur asli bahasa Rusia (misalnya), maka Anda mungkin tidak peduli apakah seseorang menulis a = 10atau 10 = akarena keduanya tampak sama alami.

Sementara linguistik adalah subjek yang menarik, saya tidak pernah mempelajarinya secara formal dan tidak tahu banyak bahasa. Semoga saya telah memberikan contoh-contoh yang cukup.

Pekerjaan
sumber
4
... dan dalam bahasa Prancis, 81 dikatakan sebagai "empat kali dua puluh satu" ... :)
Martin Sojka
1
@ Martin, saya percaya Denmark sangat mirip.
CVn
7
@ Martin Itu benar-benar aneh, karena empat kali dua puluh satu adalah 84.
Peter Olson
6
@ Peter: Anda salah tanda kurung, itu(four times twenty) one
SingleNegationElimination
4
@Job: Membaca "Jika 18 tahun kamu Mary ...", aku tak terelakkan teringat pada Yoda yang mengatakan "Ketika sembilan ratus tahun kamu mencapai, terlihat sebaik kamu tidak akan, hmm?" di Return of the Jedi :-)
joriki
11

Dimulai dengan FORTRAN pada 1950-an. Di mana FORTRAN adalah singkatan dari FORmula TRANslation - rumus yang dimaksud adalah persamaan aljabar sederhana yang oleh konvensi selalu menetapkan ke kiri.

Sebaliknya, COBOL kontemporer dekat ini dimaksudkan seperti bahasa Inggris dan ditugaskan ke kanan (kebanyakan!).

MOVE 1 TO COUNTER.
ADD +1 TO LINE-CNT.
MULTIPLY QTY BY PRICE GIVING ITEM-PRICE.
James Anderson
sumber
Saya pikir ini adalah contoh terbaik di sini karena menggambarkan konteks dalam bahasa yang dapat dibaca oleh penutur bahasa Inggris yang umum tetapi memiliki tugas yang tepat. Saya mengatakan itu penting karena sejumlah besar orang mengatakan dalam bahasa Inggris itu hanya akan membaca dari kiri ke kanan untuk tugas masuk akal, yang sama sekali tidak benar.
Joshua Hedges
5

Nah, seperti yang ditunjukkan @ diceguyd30, ada kedua notasi.

  • <Identifier> = <Value>berarti "biarkan Identifier menjadi Nilai ". Atau untuk memperluas itu: Tentukan (atau definisikan ulang) variabel Identifier to Value .
  • <Value> -> <Identifier>berarti "menyimpan Nilai untuk Pengidentifikasi ". Atau untuk memperluas itu: Masukkan Nilai ke lokasi yang ditunjuk oleh Identifier .

Tentu saja, secara umum Pengenal sebenarnya bisa berupa nilai-L.

Pendekatan pertama menghormati konsep abstrak variabel, pendekatan kedua lebih tentang penyimpanan aktual.

Perhatikan bahwa pendekatan pertama juga umum dalam bahasa, yang tidak memiliki tugas. Juga mencatat, bahwa variabel definisi dan tugas yang relatif dekat <Type> <Identifier> = <Value>vs <Identifier> = <Value>.

back2dos
sumber
3

Seperti yang telah disebutkan, cukup baik semua bahasa komputer awal bekerja seperti itu. Misalnya FORTRAN, yang datang bertahun-tahun sebelum BASIC.

Sebenarnya sangat masuk akal untuk memiliki variabel yang ditugaskan di sebelah kiri ekspresi penugasan. Dalam beberapa bahasa, Anda mungkin memiliki beberapa rutinitas kelebihan beban yang berbeda dengan NAMA SAMA, menghasilkan berbagai jenis hasil. Dengan membiarkan kompilator melihat jenis variabel yang ditugaskan terlebih dahulu, ia tahu mana yang overload rutin untuk memanggil, atau apa yang dilemparkan implisit untuk menghasilkan ketika mengkonversi dari (misalnya) integer ke float. Itu sedikit penjelasan yang sederhana, tetapi mudah-mudahan Anda mendapatkan idenya.

Dave Jewell
sumber
2
Saya mengerti penjelasan Anda, tetapi tidak bisakah kompiler hanya melihat ke depan sampai akhir pernyataan?
voithos
Itu mungkin membuat lexer lebih sederhana dalam bahasa saat ini, tetapi berapa banyak bahasa pemrograman bahkan mendukung metode bernama, apalagi metode kelebihan beban, ketika sintaksis seperti ini baru?
CVn
2
Hai @voithos. Ya - kompiler dapat melihat ke depan, tetapi itu mungkin akan menjadi tingkat kompleksitas yang tidak dapat diterima di awal-awal penulisan kompiler - yang seringkali merupakan pembuat kode tangan! Saya pikir menempatkan variabel yang ditugaskan di sebelah kiri adalah pilihan pragmatis: lebih mudah bagi manusia dan mesin untuk mengurai.
Dave Jewell
Saya pikir itu akan menjadi hal sepele untuk penugasan untuk menetapkan ke kanan. Ketika ekspresi seperti 3 + 4 == 6 + 7, kedua belah pihak dievaluasi sebelum operator, karena bahasa didefinisikan secara rekursif. Elemen bahasa 'variabel = ekspresi', dapat dengan mudah diubah menjadi 'ekspresi = variabel'. Apakah atau tidak itu menyebabkan situasi ambigu tergantung pada sisa bahasa.
Kratz
@Ratz - itu tentu benar untuk kompiler sekarang, tetapi mungkin ada masalah kecil untuk bahasa yang sangat tua ditafsirkan yang bekerja dengan sumber tokenized. OTOH, yang mungkin lebih disukai variabel-on-the-right daripada variabel-on-the-left.
Steve314
3

Ini bisa menjadi sisa dari algoritma parsing awal. Ingat bahwa parsing LR hanya ditemukan pada tahun 1965, dan bisa jadi parser LL mengalami kesulitan (dalam batasan waktu dan ruang mesin pada saat itu) sebaliknya. Mempertimbangkan:

identifier = function();
function();

Keduanya jelas disatukan dari token kedua. Di samping itu,

function() = identifier;
function();

Tidak menyenangkan. Ini semakin buruk ketika Anda mulai ekspresi penugasan bersarang.

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

Tentu saja, lebih mudah untuk ambigu untuk mesin juga berarti lebih mudah untuk ambigu bagi manusia. Contoh mudah lainnya adalah mencari inisialisasi dari setiap pengenal yang diberikan.

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

Mudah, lihat saja sisi kiri. Sisi kanan, di sisi lain

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

Terutama ketika Anda tidak dapat membuat grepkartu, jauh lebih sulit untuk menemukan pengenal yang Anda inginkan.

DeadMG
sumber
Persis poin yang saya pikirkan, ya.
voithos
2

Bahasa asssembly memiliki tujuan sebagai bagian dari opcode kiri. Bahasa tingkat yang lebih tinggi cenderung mengikuti konvensi bahasa pendahulunya.

Ketika Anda melihat =(atau :=untuk dialek Pascalish), Anda dapat melafalkannya sebagai is assigned the value, maka sifat dari kiri ke kanan akan masuk akal (karena kami juga membaca dari kiri ke kanan dalam kebanyakan bahasa). Karena bahasa pemrograman sebagian besar dikembangkan oleh orang-orang yang membaca kiri-ke-kanan, konvensi macet.

Ini adalah jenis ketergantungan jalan . Saya kira jika pemrograman komputer ditemukan oleh orang-orang yang berbicara bahasa Ibrani atau Arab (atau bahasa kanan-ke-kiri lainnya), maka saya curiga kita akan meletakkan tujuan di sebelah kanan.

Tangurena
sumber
Ya, tapi saya curiga bahwa teks dalam editor akan disejajarkan dengan benar juga ...
voithos
8
Anda tidak dapat menggeneralisasi seperti itu tentang bahasa assembly. Mereka berbeda di mana operan tujuan.
quick_now
2
@quickly_now: benar; pada kenyataannya, sebagian besar bahasa mesin primitif (bahkan tidak perakit dengan standar saat ini) bahkan tidak memiliki tujuan, karena biasanya hanya ada satu atau dua akumulator tujuan umum. sebagian besar operasi menyiratkan akumulator sebagai tujuan, kecuali untuk opcode 'store', yang hanya menentukan alamat memori dan bukan sumbernya (yang merupakan akumulator). Saya benar-benar tidak berpikir itu berpengaruh pada sintaks penugasan untuk bahasa seperti ALGOL.
Javier
3
@ Tangurena - Beberapa bahasa assembler memiliki destimasi di sebelah kiri. Bukan dari opcode (itu adalah kode objek yang dirakit), tetapi di sebelah kiri daftar argumen untuk mnemonic instruksi. Namun, yang lain memiliki tujuan di sebelah kanan. Di 68000 assembler, Anda akan menulis mov.b #255, d0, misalnya, di mana d0register untuk ditugaskan. Perakit yang lebih tua hanya memiliki satu argumen per instruksi. Di 6502 LDA #255(Load Accumulator), Anda bisa berargumen bahwa Adi sebelah kiri, tetapi juga di sebelah kiri di STA wherever(Store Accumulator).
Steve314
2
Dan bahkan Intel 4004 (nenek moyang 4-bit utama dari keluarga 8086, dengan 8008 dan 8080 di antaranya) dikembangkan setelah penugasan dalam bahasa tingkat tinggi. Jika Anda berasumsi bahwa seri 8086 mewakili apa yang dilakukan assembler di tahun 50-an dan sebelumnya, saya sangat meragukan itu benar.
Steve314
2

Untuk apa layak, sebagian pernyataan dalam COBOL dibaca dari kiri ke kanan, sehingga dua operan diberi nama pertama, dan tujuan yang terakhir, seperti: multiply salary by rate giving tax.

Namun saya tidak akan, menyarankan bahwa siswa Anda mungkin lebih suka COBOL, karena takut bahwa saya (cukup benar) ditandai karena membuat komentar yang begitu rendah, kasar, dan hambar! :-)

Jerry Coffin
sumber
1

dia mengatakan bahwa kiri-ke-kanan tampak lebih alami baginya, karena itulah sebagian besar dari kita membaca bahasa alami.

Saya pikir ini adalah kesalahan. Di satu sisi, Anda dapat mengatakan "tetapkan 10 ke x" atau "pindahkan 10 ke x". Di sisi lain, Anda dapat mengatakan "atur x ke 10" atau "x menjadi 10".

Dengan kata lain, tergantung pada pilihan kata kerja Anda, variabel ditugaskan-ke mungkin atau mungkin bukan subjek, dan mungkin atau mungkin tidak di sebelah kiri. Jadi "apa yang alami" hanya bergantung sepenuhnya pada pilihan kebiasaan Anda untuk kata-kata untuk mewakili tugas.

Steve314
sumber
0

Dalam pseudocode, operator penugasan biasanya ditulis di sebelah kanan. Sebagai contoh

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

Dalam kalkulator Casio, bahkan varian yang tidak dapat diprogram, variabel penugasan juga ditampilkan di sebelah kanan

A+2B → C

Di Forth variabelnya ada di kanan juga

expression variable !

Pada x86, sintaks Intel memiliki tujuan di sebelah kiri, tetapi sintaks GAS membalik urutan, membuat beberapa kebingungan bagi banyak orang, terutama pada instruksi mengenai urutan parameter seperti pengurangan atau perbandingan. Instruksi-instruksi ini sama dalam 2 dialek yang berbeda

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

Keduanya memindahkan nilai dalam rbx ke rax. Tidak ada bahasa rakitan lain yang saya tahu tulis tujuan di sebelah kanan seperti GAS.

Beberapa platform meletakkan ekspresi di sebelah kiri dan variabel di sebelah kanan:

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

Sebagian besar bahasa menetapkan nilai ke kiri, salah satu alasannya adalah mudah menyelaraskan operator, lebih mudah membaca dan mengenali variabel, karena operator penugasan dan posisi variabel tidak akan bervariasi secara liar di dalam garis, dan lebih mudah dibaca sebagai + msgstr "biarkan variabel menjadi beberapa nilai".

Namun beberapa orang lebih suka mengatakan "pindahkan nilai x ke y" dan tulis variabel di sebelah kanan.

phuclv
sumber
-1

Saya pikir ini mengikuti cara berpikir logis.
Harus ada kotak (variabel) terlebih dahulu, lalu Anda meletakkan objek (nilai) di dalamnya.
Anda tidak meletakkan benda di udara dan kemudian meletakkan sebuah kotak di sekitarnya.

Petruza
sumber
2
ya kamu lakukan. dalam kebanyakan bahasa sisi kanan dievaluasi sebelum yang kiri.
Javier
3
Ini adalah jenis "Mengemudi di sisi kanan jalan". Tampaknya logis tetapi hanya karena cara Anda selalu melakukannya. Semua negara unggul mengemudi di Kiri.
James Anderson
1
@JamesAnderson negara-negara superior? : o
nawfal
Anda benar, itu hanya logis untuk sistem penulisan kiri ke kanan sebagai alfabet roman, yang saya kira digunakan oleh hampir setiap bahasa pemrograman, jika tidak semua.
Petruza