Ekspresi versus Pernyataan


432

Saya bertanya tentang c #, tapi saya menganggapnya sama di sebagian besar bahasa lain.

Adakah yang memiliki definisi ekspresi dan pernyataan yang baik dan apa perbedaannya?


4
Saya menemukan jawaban yang Anda pilih tidak jelas. Ekspresi juga melakukan sesuatu - itu mengevaluasi ke nilai. Saya memberikan jawaban yang tidak ambigu.
Shelby Moore III

4
@ShelbyMooreIII - Tidak ambigu dan juga salah. Jawaban yang diterima adalah kata-kata secara informal, tetapi kata-kata itu membuatnya mudah dipahami - dan yang paling penting, makna yang disampaikannya akurat.
Justin Morgan

@JustinMorgan Sedihnya, definisi dalam jawaban yang diterima juga jelas salah ("mengevaluasi nilai" / "sebaris kode") untuk sebagian besar bahasa kontemporer termasuk yang mirip-C: ekspresi dapat digunakan dalam konteks yang tidak dievaluasi dan pernyataan tidak memiliki apa-apa harus dilakukan dengan garis. Bahkan ada beberapa penjelasan, jawaban singkatnya membingungkan dan menyesatkan.
FrankHB

Jawaban:


521

Ekspresi: Sesuatu yang mengevaluasi suatu nilai. Contoh: Pernyataan 1 + 2 / x
: Baris kode yang melakukan sesuatu. Contoh: GOTO 100

Dalam bahasa pemrograman tujuan umum paling awal, seperti FORTRAN, perbedaannya sangat jelas. Di FORTRAN, pernyataan adalah satu unit eksekusi, hal yang Anda lakukan. Satu-satunya alasan itu tidak disebut "garis" adalah karena kadang-kadang membentang beberapa baris. Ekspresi sendiri tidak bisa melakukan apa-apa ... Anda harus menugaskannya ke variabel.

1 + 2 / X

adalah kesalahan dalam FORTRAN, karena tidak melakukan apa-apa. Anda harus melakukan sesuatu dengan ekspresi itu:

X = 1 + 2 / X

FORTRAN tidak memiliki tata bahasa seperti yang kita kenal sekarang — gagasan itu diciptakan, bersama dengan Backus-Naur Form (BNF), sebagai bagian dari definisi Algol-60. Pada titik itu perbedaan semantik ("memiliki nilai" versus "melakukan sesuatu") diabadikan dalam sintaksis : satu jenis ungkapan adalah ekspresi, dan yang lain adalah pernyataan, dan pengurai dapat membedakan mereka.

Desainer bahasa kemudian mengaburkan perbedaan: mereka memungkinkan ekspresi sintaksis untuk melakukan sesuatu, dan mereka mengizinkan pernyataan sintaksis yang memiliki nilai. Contoh bahasa populer paling awal yang masih bertahan adalah C. Desainer C menyadari bahwa tidak ada salahnya dilakukan jika Anda diizinkan untuk mengevaluasi ekspresi dan membuang hasilnya. Dalam C, setiap ekspresi sintaksis dapat dibuat menjadi pernyataan hanya dengan menempelkan tanda titik koma di akhir:

1 + 2 / x;

adalah pernyataan yang sepenuhnya sah meskipun sama sekali tidak ada yang terjadi. Demikian pula, dalam C, ekspresi dapat memiliki efek samping — ia dapat mengubah sesuatu.

1 + 2 / callfunc(12);

karena callfuncmungkin hanya melakukan sesuatu yang bermanfaat.

Setelah Anda membiarkan ekspresi apa pun menjadi pernyataan, Anda mungkin juga mengizinkan operator penugasan (=) di dalam ekspresi. Itu sebabnya C memungkinkan Anda melakukan hal-hal seperti

callfunc(x = 2);

Ini mengevaluasi ekspresi x = 2 (menetapkan nilai 2 ke x) dan kemudian meneruskannya (2) ke fungsi callfunc.

Pengaburan ekspresi dan pernyataan ini terjadi di semua turunan C (C, C ++, C #, dan Java), yang masih memiliki beberapa pernyataan (seperti while) tetapi yang memungkinkan hampir semua ungkapan untuk digunakan sebagai pernyataan (dalam penugasan C # saja, panggilan, kenaikan, dan ekspresi penurunan dapat digunakan sebagai pernyataan; lihat jawaban Scott Wisniewski ).

Memiliki dua "kategori sintaksis" (yang merupakan nama teknis untuk jenis pernyataan dan ekspresi) dapat menyebabkan duplikasi usaha. Misalnya, C memiliki dua bentuk kondisional, yaitu bentuk pernyataan

if (E) S1; else S2;

dan bentuk ekspresi

E ? E1 : E2

Dan kadang-kadang orang menginginkan duplikasi yang tidak ada: dalam standar C, misalnya, hanya pernyataan yang dapat mendeklarasikan variabel lokal baru — tetapi kemampuan ini cukup berguna sehingga kompiler GNU C menyediakan ekstensi GNU yang memungkinkan ekspresi untuk mendeklarasikan sebuah variabel lokal juga.

Desainer bahasa lain tidak menyukai duplikasi semacam ini, dan mereka melihat sejak awal bahwa jika ekspresi dapat memiliki efek samping serta nilai-nilai, maka perbedaan sintaksis antara pernyataan dan ekspresi tidak terlalu berguna — jadi mereka menyingkirkannya . Haskell, Icon, Lisp, dan ML adalah semua bahasa yang tidak memiliki pernyataan sintaksis — mereka hanya memiliki ekspresi. Bahkan pengulangan terstruktur kelas dan bentuk kondisional dianggap sebagai ekspresi, dan mereka memiliki nilai — tetapi tidak terlalu menarik.


9
Jika saya tidak salah menafsirkan Anda di sini, Anda tampaknya mengklaim bahwa "(setf (foo ketiga) 'angsa)" adalah ekspresi, bukan pernyataan, keduanya karena Lisp, yang "tidak memiliki pernyataan," dan karena Lisp lebih dari satu dekade lebih tua dari C, yang merupakan "bahasa populer paling awal untuk mengaburkan garis [antara ekspresi dan pernyataan]." Bisakah menjelaskan detail itu kepada saya?
cjs

2
@Curt Sampson, sudahkah Anda menanyakan hal itu sebagai pertanyaan terpisah?
Kelly S. Prancis

5
Jika saya tidak salah, callfunc(x = 2);lolos xke callfunc, tidak 2. Jika xfloat, callfunc(float)akan dipanggil, bukan callfunc(int). Dan di C ++, jika Anda beralih x=yke func, dan funcmengambil referensi dan mengubahnya, itu berubah x, tidak y.
Gabriel

Dalam jawaban di atas, ada tertulis bahwa "Haskell, ... semua bahasa yang tidak memiliki pernyataan sintaksis - mereka hanya memiliki ekspresi". Saya ingin tahu mengapa whereklausa dalam haskell dianggap sebagai ekspresi dan bukan pernyataan. learnyouahaskell.com/syntax-in-functions#where
skgbanga

@ skgbanga Saya percaya wheresebenarnya adalah bagian dari deklarasi fungsi, bukan ekspresi atau pernyataan.
Akangka

22
  • ekspresi adalah apa pun yang menghasilkan nilai: 2 + 2
  • pernyataan adalah salah satu "blok" dasar dari eksekusi program.

Perhatikan bahwa dalam C, "=" sebenarnya adalah operator, yang melakukan dua hal:

  • mengembalikan nilai subekspresi kanan.
  • menyalin nilai dari subekspresi tangan kanan ke dalam variabel di sisi kiri.

Berikut adalah ekstrak dari tata bahasa ANSI C. Anda dapat melihat bahwa C tidak memiliki banyak jenis pernyataan ... mayoritas pernyataan dalam suatu program adalah pernyataan ekspresi, yaitu ekspresi dengan tanda titik koma di bagian akhir.

statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html


2
Logika salah tentang apa pernyataan itu. Program deklaratif juga dapat mengeksekusi, tetapi program deklaratif tidak memiliki pernyataan. Pernyataan adalah dan tidak "efek samping" , yaitu keharusan. lih. jawaban saya .
Shelby Moore III

15

Ekspresi adalah sesuatu yang mengembalikan nilai, sedangkan pernyataan tidak.

Sebagai contoh:

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

Kesepakatan besar di antara keduanya adalah Anda dapat membuat rantai ekspresi bersama, sedangkan pernyataan tidak dapat dirantai.


6
Pernyataan yang pasti bisa dirantai. {stmt1; stmt2; stmt3;} adalah sebuah rantai, dan itu juga pernyataan (gabungan) itu sendiri.
Hugh Allen

5
foo.voidFunc(1);adalah ekspresi dengan nilai void. whiledan ifmerupakan pernyataan.
tzot

Saya ingin tahu tentang pernyataan yang tidak dirantai. Akankah sesuatu seperti "jika (x> 1) kembali;" dianggap merantai dua pernyataan bersama?
Simon Tewsi

1
@SimonTewsi Saya percaya returnini dianggap sebagai pernyataan.
RastaJedi

1
@SimonTewsi Pernyataan kembali di sini secara implisit di dalam blok pernyataan if, jadi itu adalah bagian dari pernyataan if, tidak dirantai dengan itu. Compiler memungkinkan kita untuk menghilangkan kawat gigi di sini, karena itu adalah satu baris blok.
user2597608

9

Anda dapat menemukan ini di wikipedia , tetapi ekspresi dievaluasi ke beberapa nilai, sedangkan pernyataan tidak memiliki nilai yang dievaluasi.

Dengan demikian, ekspresi dapat digunakan dalam pernyataan, tetapi tidak sebaliknya.

Perhatikan bahwa beberapa bahasa (seperti Lisp, dan saya percaya Ruby, dan banyak lainnya) tidak membedakan pernyataan vs ekspresi ... dalam bahasa seperti itu, semuanya adalah ekspresi dan dapat dirantai dengan ekspresi lain.


8

Untuk penjelasan tentang perbedaan penting dalam kemampuan menyusun (chainability) ekspresi vs pernyataan, referensi favorit saya adalah makalah penghargaan Turing karya John Backus, Bisakah pemrograman dibebaskan dari gaya von Neumann? .

Bahasa imperatif (Fortran, C, Java, ...) menekankan pernyataan untuk menyusun program, dan memiliki ekspresi sebagai semacam after-mind. Bahasa fungsional menekankan ekspresi. Bahasa yang berfungsi murni memiliki ekspresi yang begitu kuat sehingga pernyataan tidak bisa dihilangkan sama sekali.


5

Ekspresi dapat dievaluasi untuk mendapatkan nilai, sedangkan pernyataan tidak mengembalikan nilai (mereka bertipe batal ).

Ekspresi panggilan fungsi juga dapat dianggap sebagai pernyataan, tetapi kecuali jika lingkungan eksekusi memiliki variabel bawaan khusus untuk menyimpan nilai yang dikembalikan, tidak ada cara untuk mengambilnya.

Bahasa yang berorientasi pada pernyataan mengharuskan semua prosedur untuk menjadi daftar pernyataan. Bahasa berorientasi ekspresi, yang mungkin semua bahasa fungsional, adalah daftar ekspresi, atau dalam kasus LISP, satu ekspresi S panjang yang mewakili daftar ekspresi.

Meskipun kedua jenis dapat dikomposisikan, sebagian besar ekspresi dapat dikomposisikan secara sewenang-wenang selama kedua jenis tersebut cocok. Setiap jenis pernyataan memiliki caranya sendiri untuk menyusun pernyataan lain, jika mereka dapat melakukan itu semua. Foreach dan jika pernyataan mensyaratkan baik statment tunggal atau bahwa semua pernyataan bawahan masuk dalam blok pernyataan, satu demi satu, kecuali substitusi memungkinkan substitusi mereka sendiri.

Pernyataan juga dapat mencakup ekspresi, di mana ekspresi tidak benar-benar menyertakan pernyataan apa pun. Satu pengecualian, bagaimanapun, akan menjadi ekspresi lambda, yang mewakili suatu fungsi, dan dengan demikian dapat mencakup apa saja yang dapat dikerjakan fungsi kecuali jika bahasanya hanya memungkinkan untuk lambda terbatas, seperti lambda ekspresi tunggal Python.

Dalam bahasa berbasis ekspresi, yang Anda butuhkan adalah ekspresi tunggal untuk fungsi karena semua struktur kontrol mengembalikan nilai (banyak dari mereka mengembalikan NIL). Tidak perlu untuk pernyataan kembali karena ekspresi yang terakhir dievaluasi dalam fungsi adalah nilai kembali.


Jenis pernyataan adalah tipe terbawah. Voidbukan tipe bawah. Lihat jawaban saya .
Shelby Moore III

1
Bukankah tipe null adalah tipe terbawah (nilai tunggal null)? Bukankah voidlebih seperti tipe unit (tetapi dengan nilai tunggal tidak dapat diakses)?
Mark Cidade

Jika voidadalah tipe pengembalian fungsi yang tidak pernah kembali (misalnya fungsi yang throwmerupakan kesalahan), itu adalah tipe bawah . Sebaliknya voidadalah tipe unit . Anda benar bahwa pernyataan yang tidak dapat menyimpang, memiliki tipe unit. Tapi pernyataan yang bisa berbeda adalah tipe terbawah. Karena Teorema Henti, kami biasanya tidak dapat membuktikan bahwa suatu fungsi tidak berbeda, jadi saya pikir unit adalah fiksi. Tipe bawah tidak dapat memiliki nilai, jadi tidak dapat memiliki nilai tunggal null.
Shelby Moore III

1
Mengenai apa yang saya katakan tiga tahun lalu, saya tidak tahu apakah saya masih menganggap pernyataan memiliki tipe kosong atau tipe apa pun. Dalam bahasa berbasis pernyataan yang saya kenal, hanya nilai dan apa pun yang menyimpan atau mengembalikan nilai (misalnya, ekspresi, variabel, anggota, dan fungsi) dapat memiliki jenis. Saya biasanya menganggap tipe bawah sebagai set kosong (tidak ada nilai) dan segala sesuatu yang tidak ada secara ontologis akan memiliki tipe ini. Sebuah nullnilai adalah benar-benar sebuah pseudovalue yang menunjukkan bahwa referensi mengacu pada sesuatu yang tidak ada.
Mark Cidade

1
Mark I menghargai rasionalitas respons Anda. Anda pada dasarnya mengeluarkan kata-kata dari mulut saya Dan saya harap jelas bahwa saya mengakui kepada Anda bahwa Anda benar untuk meningkatkan poin unit. Saya pikir kita setuju. Saya tidak akan repot-repot menyebutkan ini, tetapi tampaknya beberapa orang di sini berpikir saya bersikap negatif. Saya hanya mencoba untuk menjadi faktual.
Shelby Moore III

4

Sederhananya: ekspresi mengevaluasi nilai, pernyataan tidak.


Jadi, apa yang dilakukan pernyataan? Tidak ada?
Shelby Moore III

1
Itu bisa melakukan sesuatu, tetapi tidak mengevaluasi apa pun. Yaitu, Anda tidak dapat menetapkan hasilnya ke variabel, sedangkan Anda bisa dengan ekspresi.
Matthew Schinckel

Dan karenanya pernyataan harus memiliki efek samping, seperti yang dinyatakan oleh jawaban saya yang berat. Utilitas apa lagi yang bisa dimiliki oleh suatu pernyataan? Bahkan jika NO-OP dianggap sebagai pernyataan (itu hanya "pernyataan" dalam tata bahasa tetapi tidak pada lapisan semantik karena dihapus setelah parsing dan semantik adalah apa yang kita bahas di sini), itu tidak akan menjelaskan apa sih utilitas umum pernyataan adalah.
Shelby Moore III

1
Pernyataan @ShelbyMooreIII tidak perlu melakukan apa pun atau memiliki efek samping. misalnya, {}adalah pernyataan. Menempatkan kata dalam kutipan menakut-nakuti tidak mengubah itu. Pernyataan adalah konstruksi sintaksis dengan semantik. Tidak ada yang namanya "lapisan semantik" - Anda tampaknya mengacu pada eksekusi . Anda mengatakan Anda mencoba untuk menjadi akurat, tetapi Anda gagal dalam hal itu. Keluhan Anda tentang "ketidaktahuan pemilih yang rendah" adalah murni ad hominem; Anda tidak memiliki informasi tentang kondisi mental para downvoters.
Jim Balter

Ya, semua orang salah kecuali yang tidak jujur ​​secara intelektual. {}didefinisikan sebagai pernyataan dalam spesifikasi bahasa C #.
Jim Balter

4

Beberapa hal tentang bahasa berbasis ekspresi:


Paling penting: Semuanya mengembalikan nilai


Tidak ada perbedaan antara kurung keriting dan kurung untuk membatasi blok kode dan ekspresi, karena semuanya adalah ekspresi. Ini tidak mencegah pelingkupan leksikal: Sebuah variabel lokal dapat didefinisikan untuk ekspresi di mana definisi itu terkandung dan semua pernyataan yang terkandung di dalamnya, misalnya.


Dalam bahasa berbasis ekspresi, semuanya mengembalikan nilai. Ini bisa agak aneh pada awalnya - Apa yang (FOR i = 1 TO 10 DO (print i))kembali?

Beberapa contoh sederhana:

  • (1) kembali 1
  • (1 + 1) kembali 2
  • (1 == 1) kembali TRUE
  • (1 == 2) kembali FALSE
  • (IF 1 == 1 THEN 10 ELSE 5) kembali 10
  • (IF 1 == 2 THEN 10 ELSE 5) kembali 5

Beberapa contoh yang lebih kompleks:

  • Beberapa hal, seperti beberapa pemanggilan fungsi, tidak benar-benar memiliki nilai yang berarti untuk dikembalikan (Hal-hal yang hanya menghasilkan efek samping?). Memanggil OpenADoor(), FlushTheToilet()atau TwiddleYourThumbs()akan mengembalikan semacam nilai biasa, seperti OK, Selesai, atau Sukses.
  • Ketika beberapa ekspresi tidak bertautan dievaluasi dalam satu ekspresi yang lebih besar, nilai hal terakhir yang dievaluasi dalam ekspresi besar menjadi nilai ekspresi besar. Untuk mengambil contoh (FOR i = 1 TO 10 DO (print i)), nilai for loop adalah "10", itu menyebabkan (print i)ekspresi dievaluasi 10 kali, setiap kali mengembalikan i sebagai string. Waktu terakhir melalui pengembalian 10, jawaban akhir kami

Seringkali diperlukan sedikit perubahan pola pikir untuk mendapatkan yang terbaik dari bahasa berbasis ekspresi, karena fakta bahwa semuanya adalah ekspresi memungkinkan untuk 'menyejajarkan' banyak hal

Sebagai contoh cepat:

 FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO
 (
    LotsOfCode
 )

adalah pengganti yang valid untuk berbasis non-ekspresi

IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 
FOR i = 1 TO TempVar DO
(    
    LotsOfCode  
)

Dalam beberapa kasus, tata letak yang diizinkan oleh kode berbasis ekspresi terasa lebih alami bagi saya

Tentu saja, ini bisa menimbulkan kegilaan. Sebagai bagian dari proyek hobi dalam bahasa scripting berbasis ekspresi yang disebut MaxScript, saya berhasil membuat garis monster ini

IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO
(
    LotsOfCode
)

2

Pernyataan adalah kasus khusus ekspresi, satu dengan void bertipe. Kecenderungan bahasa untuk memperlakukan pernyataan berbeda sering menyebabkan masalah, dan akan lebih baik jika mereka digeneralisasikan dengan benar.

Sebagai contoh, di C # kami memiliki Func<T1, T2, T3, TResult>kumpulan delegasi generik yang sangat berguna . Tetapi kita juga harus memiliki perangkat yang sesuai Action<T1, T2, T3>, dan pemrograman dengan tujuan umum tingkat tinggi harus terus digandakan untuk menangani bifurkasi yang tidak menguntungkan ini.

Contoh sepele - fungsi yang memeriksa apakah referensi nol sebelum memanggil ke fungsi lain:

TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
                  where TValue : class
{
    return (value == null) ? default(TValue) : func(value);
}

Mungkinkah kompiler menangani kemungkinan TResultkeberadaan void? Iya. Yang harus dilakukan adalah mengharuskan pengembalian diikuti oleh ekspresi yang bertipe void. Hasil default(void)akan bertipe void, dan fungsi yang dilewatkan harus berupa Func<TValue, void>(yang akan setara denganAction<TValue> ).

Sejumlah jawaban lain menyiratkan bahwa Anda tidak dapat membuat pernyataan seperti yang Anda dapat dengan ekspresi, tetapi saya tidak yakin dari mana ide ini berasal. Kita bisa memikirkan ;yang muncul setelah pernyataan sebagai operator infiks biner, mengambil dua ekspresi tipe voiddan menggabungkannya ke dalam ekspresi tipe tunggal void.


Pernyataan bukan merupakan kasus ekspresi khusus. Dalam beberapa bahasa (yaitu sebagian besar penerus C), sebenarnya sebaliknya.
Akangka

2

Pernyataan -> Instruksi untuk mengikuti
Ekspresi berurutan -> Evaluasi yang mengembalikan nilai

Pernyataan pada dasarnya seperti langkah, atau instruksi dalam suatu algoritma, hasil dari eksekusi pernyataan adalah aktualisasi dari penunjuk instruksi (disebut assembler)

Ekspresi tidak menyiratkan dan urutan eksekusi pada pandangan pertama, tujuannya adalah untuk mengevaluasi dan mengembalikan nilai. Dalam bahasa pemrograman imperatif, evaluasi suatu ekspresi memiliki urutan, tetapi itu hanya karena model imperatif, tetapi itu bukan esensi mereka.

Contoh Pernyataan:

for
goto
return
if

(semuanya menyiratkan kemajuan baris (pernyataan) eksekusi ke baris lain)

Contoh ungkapan:

2+2

(Itu tidak menyiratkan gagasan eksekusi, tetapi evaluasi)


Bagaimana dengan efek sampingnya?
Austin Henley

@AustinHenley tidak ada persyaratan untuk itu. Bahkan, ekspresi pasti dapat memiliki efek samping.
Akangka

1

Pernyataan ,

Pernyataan adalah blok bangunan prosedural dari mana semua program C # dibangun. Pernyataan dapat mendeklarasikan variabel lokal atau konstan, memanggil metode, membuat objek, atau menetapkan nilai ke variabel, properti, atau bidang.

Serangkaian pernyataan dikelilingi oleh kurung kurawal membentuk satu blok kode. Badan metode adalah salah satu contoh blok kode.

bool IsPositive(int number)
{
    if (number > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Pernyataan dalam C # sering mengandung ekspresi. Ekspresi dalam C # adalah fragmen kode yang berisi nilai literal, nama sederhana, atau operator dan operannya.

Ekspresi ,

Ekspresi adalah fragmen kode yang dapat dievaluasi ke nilai tunggal, objek, metode, atau namespace. Dua jenis ekspresi paling sederhana adalah literal dan nama-nama sederhana. Literal adalah nilai konstan yang tidak memiliki nama.

int i = 5;
string s = "Hello World";

Baik i dan s adalah nama sederhana yang mengidentifikasi variabel lokal. Ketika variabel-variabel tersebut digunakan dalam ekspresi, nilai variabel diambil dan digunakan untuk ekspresi.


Saya lebih suka menulis if(number >= 0) return true; else return false;atau bahkan lebih baik bool? IsPositive(int number) { if(number > 0) return true; else if(number < 0) return false; else return null;}:)
Mahdi Tahsildari

1

Saya lebih suka arti dari statementpengertian logika formal kata. Ini adalah salah satu yang mengubah keadaan satu atau lebih variabel dalam perhitungan, memungkinkan pernyataan benar atau salah dibuat tentang nilainya.

Saya kira akan selalu ada kebingungan dalam dunia komputasi dan sains secara umum ketika terminologi atau kata-kata baru diperkenalkan, kata-kata yang sudah ada 'ditata ulang' atau pengguna tidak mengetahui terminologi yang ada, mapan, atau 'tepat' untuk apa yang mereka gambarkan.


1

Saya tidak begitu puas dengan jawaban di sini. Saya melihat tata bahasa untuk C ++ (ISO 2008) . Namun mungkin demi didaktik dan pemrograman, jawabannya mungkin cukup untuk membedakan kedua elemen (kenyataannya terlihat lebih rumit).

Pernyataan terdiri dari nol atau lebih ekspresi, tetapi juga bisa berupa konsep bahasa lainnya. Ini adalah formulir Extended Backus Naur untuk tata bahasa (kutipan untuk pernyataan):

statement:
        labeled-statement
        expression-statement <-- can be zero or more expressions
        compound-statement
        selection-statement
        iteration-statement
        jump-statement
        declaration-statement
        try-block

Kita bisa melihat konsep lain yang dianggap pernyataan dalam C ++.

  • ekspresi-pernyataan s menjelaskan sendiri (pernyataan dapat terdiri dari nol atau lebih ekspresi, baca tata bahasa dengan hati-hati, sulit)
  • casemisalnya adalah pernyataan berlabel
  • pernyataan pemilihan adalah if if/else,case
  • iterasi-pernyataan s adalah while, do...while,for (...)
  • melompat-pernyataan s adalah break, continue, return(dapat kembali ekspresi),goto
  • deklarasi-pernyataan adalah seperangkat deklarasi
  • try-block adalah pernyataan yang mewakili try/catchblok
  • dan mungkin ada beberapa lagi tata bahasa

Ini adalah kutipan yang menunjukkan bagian ekspresi:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • ekspresi atau sering berisi tugas
  • bersyarat ekspresi (suara menyesatkan) mengacu pada penggunaan operator ( +, -, *, /, &, |, &&, ||, ...)
  • throw-expression - eh? yang throwklausul adalah ekspresi terlalu

0

Pernyataan kalimat secara tata bahasa lengkap. Ekspresi tidak. Sebagai contoh

x = 5

dibaca sebagai "x mendapat 5." Ini adalah kalimat lengkap. Kode

(x + 5)/9.0

berbunyi, "x plus 5 semua dibagi dengan 9.0." Ini bukan kalimat lengkap. Pernyataan

while k < 10: 
    print k
    k += 1

adalah kalimat lengkap. Perhatikan bahwa header loop tidak; "while k <10," adalah klausa bawahan.


whileadalah ungkapan adalah beberapa bahasa seperti Scala. Anda menggabungkan tata bahasa dengan mengetik. Lihat jawaban saya .
Shelby Moore III

Inilah loop sementara dalam scala: tutorialspoint.com/scala/scala_while_loop.htm Loop dengan predikatnya dan tanpa isi bukan kalimat yang lengkap secara tata bahasa. Itu bukan ekspresi penuh. Anda membutuhkan tubuh untuk melengkapinya sebagai ekspresi.
ncmathsadist

A whiledengan tubuh masih merupakan ekspresi dalam Scala. Ini juga bisa menjadi pernyataan jika itu menciptakan efek samping, yang memungkinkan jawaban saya yang sangat diremehkan (ekspresi juga bisa menjadi pernyataan). Jawaban saya adalah satu-satunya yang benar. Maaf untuk semua pembaca yang tidak bisa mengerti.
Shelby Moore III

Apa yang Anda maksud dengan tata bahasa yang lengkap? Di C, (x + 5)/9.0pasti bisa berdiri sendiri sebagai pernyataan. Juga, Jika secara tata bahasa selesai, maksud Anda program yang valid, C tidak mengizinkan pernyataan berdiri sendiri sebagai satu program.
Akangka

Lengkap secara tata bahasa: merupakan kalimat lengkap.
ncmathsadist

0

Ini adalah ringkasan dari salah satu jawaban paling sederhana yang saya temukan.

awalnya Dijawab oleh Anders Kaseorg

Pernyataan adalah baris kode lengkap yang melakukan beberapa tindakan, sedangkan ekspresi adalah bagian mana pun dari kode yang mengevaluasi nilai.

Ekspresi dapat digabungkan "secara horizontal" menjadi ekspresi yang lebih besar menggunakan operator, sedangkan pernyataan hanya dapat digabungkan "secara vertikal" dengan menulis satu demi satu, atau dengan konstruksi blok.

Setiap ekspresi dapat digunakan sebagai pernyataan (yang pengaruhnya mengevaluasi ekspresi dan mengabaikan nilai yang dihasilkan), tetapi sebagian besar pernyataan tidak dapat digunakan sebagai ekspresi.

http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python


0

Dasar de-facto dari konsep-konsep ini adalah:

Ekspresi : Kategori sintaksis yang instansinya dapat dievaluasi ke suatu nilai.

Pernyataan : Kategori sintaksis yang instansinya mungkin terlibat dengan evaluasi ekspresi dan nilai hasil evaluasi (jika ada) tidak dijamin tersedia.

Selain konteks awal FORTRAN pada dekade-dekade awal, definisi ekspresi dan pernyataan dalam jawaban yang diterima jelas salah:

  • Ekspresi dapat operan tidak dinilai. Nilai tidak pernah dihasilkan darinya.
    • Subekspresi dalam evaluasi yang tidak ketat pasti tidak dapat dievaluasi.
      • Sebagian besar bahasa mirip-C memiliki apa yang disebut aturan evaluasi hubung-pendek untuk secara kondisional melewatkan beberapa evaluasi sub-ekspresi tidak mengubah hasil akhir terlepas dari efek sampingnya.
    • C dan beberapa bahasa mirip-C memiliki gagasan operan yang tidak dievaluasi yang mungkin bahkan secara normatif didefinisikan dalam spesifikasi bahasa. Konstruk semacam itu digunakan untuk menghindari evaluasi secara pasti, sehingga informasi konteks yang tersisa (misalnya jenis atau persyaratan pelurusan) dapat dibedakan secara statis tanpa mengubah perilaku setelah terjemahan program.
      • Misalnya, ekspresi yang digunakan sebagai operan sizeofoperator tidak pernah dievaluasi.
  • Pernyataan tidak ada hubungannya dengan konstruksi garis. Mereka dapat melakukan sesuatu lebih dari ekspresi, tergantung pada spesifikasi bahasa.
    • Modern Fortran, sebagai keturunan langsung dari FORTRAN tua, memiliki konsep pernyataan dieksekusi dan pernyataan nonexecutable s.
    • Demikian pula, C ++ mendefinisikan deklarasi sebagai sub-kategori tingkat atas dari unit terjemahan. Deklarasi di C ++ adalah pernyataan. (Ini tidak benar dalam C.) Ada juga ungkapan-pernyataan seperti pernyataan dieksekusi Fortran.
    • Untuk kepentingan perbandingan dengan ekspresi, hanya pernyataan "yang dapat dieksekusi" yang penting. Tetapi Anda tidak dapat mengabaikan fakta bahwa pernyataan sudah digeneralisasi untuk menjadi konstruksi yang membentuk unit terjemahan dalam bahasa yang begitu penting. Jadi, seperti yang Anda lihat, definisi kategorinya sangat bervariasi. Properti (mungkin) yang tetap dipertahankan di antara bahasa-bahasa ini adalah bahwa pernyataan diharapkan ditafsirkan dalam urutan leksikal (untuk sebagian besar pengguna, dari kiri ke kanan dan atas ke bawah).

(BTW, saya ingin menambahkan [rujukan?] Untuk jawaban mengenai materi tentang C karena saya tidak dapat mengingat apakah DMR memiliki pendapat seperti itu. Sepertinya tidak, jika tidak seharusnya tidak ada alasan untuk menjaga duplikasi fungsi dalam desain C : terutama, operator koma vs. pernyataan.)

(Alasan berikut ini bukanlah jawaban langsung terhadap pertanyaan awal, tetapi saya merasa perlu untuk mengklarifikasi sesuatu yang sudah dijawab di sini.)

Namun demikian, diragukan bahwa kita membutuhkan kategori "pernyataan" khusus dalam bahasa pemrograman untuk tujuan umum:

  • Pernyataan tidak dijamin memiliki kemampuan semantik lebih dari ekspresi dalam desain yang biasa.
    • Banyak bahasa telah berhasil meninggalkan gagasan pernyataan untuk mendapatkan desain keseluruhan yang bersih, rapi dan konsisten.
      • Dalam bahasa-bahasa seperti itu, ekspresi dapat melakukan apa saja yang dapat dilakukan oleh pernyataan gaya lama: cukup jatuhkan hasil yang tidak digunakan ketika ekspresi dievaluasi, baik dengan membiarkan hasil secara eksplisit tidak ditentukan (misalnya dalam R n Skema RS), atau memiliki nilai khusus (sebagai nilai tipe unit) tidak dapat diproduksi dari evaluasi ekspresi normal.
      • Aturan urutan leksikal evaluasi ekspresi dapat digantikan oleh operator kontrol urutan eksplisit (misalnya begindalam Skema) atau gula sintaksis dari struktur monadik.
      • Aturan urutan leksikal jenis "pernyataan" lainnya dapat diturunkan sebagai ekstensi sintaksis (menggunakan makro higienis, misalnya) untuk mendapatkan fungsionalitas sintaksis yang serupa. (Dan itu sebenarnya bisa berbuat lebih banyak .)
    • Sebaliknya, pernyataan tidak dapat memiliki aturan konvensional seperti itu, karena mereka tidak menyusun evaluasi: tidak ada gagasan umum seperti "evaluasi substatement". (Bahkan jika ada, saya ragu ada sesuatu yang lebih dari sekadar salin dan tempel dari aturan evaluasi ekspresi yang ada.)
      • Biasanya, pernyataan yang mempertahankan bahasa juga akan memiliki ekspresi untuk mengekspresikan perhitungan, dan ada subkategori tingkat atas dari pernyataan yang disimpan untuk evaluasi ekspresi untuk subkategori tersebut. Sebagai contoh, C ++ memiliki apa yang disebut ekspresi-pernyataan sebagai subkategori, dan menggunakan aturan evaluasi ekspresi nilai-dibuang untuk menentukan kasus-kasus umum evaluasi ekspresi penuh dalam konteks tersebut. Beberapa bahasa seperti C # memilih untuk memperbaiki konteks untuk menyederhanakan kasus penggunaan, tetapi lebih membengkak spesifikasi.
  • Untuk pengguna bahasa pemrograman, signifikansi pernyataan dapat membingungkan mereka lebih lanjut.
    • Pemisahan aturan ekspresi dan pernyataan dalam bahasa membutuhkan lebih banyak upaya untuk belajar bahasa.
    • Interpretasi tata bahasa yang naif menyembunyikan gagasan yang lebih penting: evaluasi ekspresi. (Ini mungkin yang paling bermasalah dari semuanya.)
      • Bahkan evaluasi ekspresi penuh dalam pernyataan dibatasi dengan urutan leksikal, subekspresi tidak (harus). Pengguna pada akhirnya harus mempelajari ini di samping aturan apa pun yang digabungkan dengan pernyataan. (Pertimbangkan cara membuat seorang pemula mendapatkan poin itu++i + ++i tidak ada artinya dalam C.)
      • Beberapa bahasa seperti Java dan C # lebih lanjut membatasi urutan evaluasi subekspresi agar diizinkan oleh ketidaktahuan aturan evaluasi. Itu bisa menjadi lebih bermasalah.
        • Ini tampaknya terlalu ditentukan untuk pengguna yang telah mempelajari ide evaluasi ekspresi. Ini juga mendorong komunitas pengguna untuk mengikuti model mental kabur dari desain bahasa.
        • Itu menggembungkan spesifikasi bahasa bahkan lebih.
        • Membahayakan optimasi dengan melewatkan ekspresi nondeterminisme pada evaluasi, sebelum primitif yang lebih rumit diperkenalkan.
      • Beberapa bahasa seperti C ++ (khususnya, C ++ 17) menetapkan konteks aturan evaluasi yang lebih halus, sebagai kompromi dari masalah di atas.
        • Itu menggembungkan spesifikasi bahasa banyak.
        • Ini sangat bertentangan dengan kesederhanaan bagi pengguna rata-rata ...

Jadi mengapa pernyataan? Bagaimanapun, sejarah sudah berantakan. Tampaknya sebagian besar perancang bahasa tidak mengambil pilihan mereka dengan hati-hati.

Lebih buruk lagi, itu bahkan memberikan beberapa penggemar sistem tipe (yang tidak cukup akrab dengan sejarah PL) beberapa kesalahpahaman bahwa sistem tipe harus memiliki hal-hal penting yang harus dilakukan dengan desain aturan yang lebih penting pada semantik operasional.

Serius, alasan tergantung pada jenis tidak begitu buruk dalam banyak kasus, tetapi khususnya tidak konstruktif dalam hal khusus ini. Bahkan para ahli dapat mengacaukan segalanya.

Misalnya, seseorang menekankan sifat mengetik dengan baik sebagai argumen sentral terhadap perlakuan tradisional atas kelanjutan yang tidak didahulukan . Meskipun kesimpulannya agak masuk akal dan wawasan tentang fungsi yang dikomposisikan OK ( tapi masih terlalu naif untuk esens ), argumen ini tidak masuk akal karena sama sekali mengabaikan pendekatan "saluran samping" dalam praktiknya seperti _Noreturn any_of_returnable_types(dalam C11) untuk dikodekan Falsum. Dan sebenarnya, mesin abstrak dengan keadaan yang tidak dapat diprediksi tidak identik dengan "komputer yang mogok".


0

Dalam bahasa pemrograman berorientasi pernyataan, blok kode didefinisikan sebagai daftar pernyataan. Dengan kata lain, pernyataan adalah sepotong sintaks yang dapat Anda masukkan ke dalam blok kode tanpa menyebabkan kesalahan sintaksis.

Wikipedia mendefinisikan pernyataan kata dengan cara yang sama

Dalam pemrograman komputer, pernyataan adalah unit sintaksis dari bahasa pemrograman imperatif yang menyatakan beberapa tindakan yang harus dilakukan. Suatu program yang ditulis dalam bahasa seperti itu dibentuk oleh urutan satu atau lebih pernyataan

Perhatikan pernyataan terakhir. (walaupun "program" dalam hal ini secara teknis salah karena C dan Java menolak program yang tidak mengandung pernyataan.)

Wikipedia mendefinisikan ekspresi kata sebagai

Ekspresi dalam bahasa pemrograman adalah entitas sintaksis yang dapat dievaluasi untuk menentukan nilainya

Ini, bagaimanapun, salah, karena di Kotlin, throw new Exception("")adalah ekspresi tetapi ketika dievaluasi, itu hanya melempar pengecualian, tidak pernah mengembalikan nilai apa pun.

Dalam bahasa pemrograman yang diketik secara statis, setiap ekspresi memiliki tipe. Namun definisi ini tidak berfungsi dalam bahasa pemrograman yang diketik secara dinamis.

Secara pribadi, saya mendefinisikan ekspresi sebagai bagian dari sintaks yang dapat disusun dengan panggilan operator atau fungsi untuk menghasilkan ekspresi yang lebih besar. Ini sebenarnya mirip dengan penjelasan ungkapan oleh Wikipedia:

Ini adalah kombinasi dari satu atau lebih konstanta, variabel, fungsi, dan operator yang diinterpretasikan oleh bahasa pemrograman (sesuai dengan aturan prioritas dan asosiasi) dan dihitung untuk menghasilkan ("mengembalikan", dalam lingkungan stateful) nilai lain

Tapi, masalahnya adalah dalam bahasa pemrograman C, diberikan fungsi executeS sesuatu seperti ini:

void executeSomething(void){
    return;
}

Apakah executeSomething()ungkapan atau itu pernyataan? Menurut definisi saya, ini adalah pernyataan karena sebagaimana didefinisikan dalam tata bahasa referensi C Microsoft,

Anda tidak dapat menggunakan nilai (tidak ada) dari ekspresi yang memiliki tipe void dengan cara apa pun, Anda juga tidak dapat mengubah ekspresi void (dengan konversi implisit atau eksplisit) ke tipe apa pun kecuali void

Tetapi halaman yang sama dengan jelas menunjukkan bahwa sintaks semacam itu adalah ekspresi.


-6

Untuk meningkatkan dan memvalidasi jawaban saya sebelumnya, definisi istilah bahasa pemrograman harus dijelaskan dari teori tipe ilmu komputer jika berlaku.

Ekspresi memiliki tipe selain tipe Bawah, yaitu memiliki nilai. Pernyataan memiliki tipe Unit atau Bawah.

Dari sini dapat disimpulkan bahwa pernyataan hanya dapat memiliki efek apa pun dalam suatu program ketika ia menciptakan efek samping, karena ia tidak dapat mengembalikan nilai atau hanya mengembalikan nilai tipe Unit yang tidak dapat dialihkan (dalam beberapa bahasa seperti a's C void) atau (seperti dalam Scala) dapat disimpan untuk evaluasi pernyataan yang tertunda.

Jelas a @pragmaatau a /*comment*/tidak memiliki tipe dan dengan demikian dibedakan dari pernyataan. Dengan demikian satu-satunya jenis pernyataan yang tidak memiliki efek samping adalah non-operasi. Non-operasi hanya berguna sebagai pengganti untuk efek samping di masa depan. Tindakan lain apa pun karena pernyataan akan menimbulkan efek samping. Sekali lagi petunjuk kompiler, misalnya @pragma, bukan pernyataan karena tidak memiliki tipe.


2
Perbedaannya tidak ada hubungannya dengan jenis ekspresi. Pernyataan yang didefinisikan secara sintaksis tidak memiliki tipe sama sekali dalam banyak bahasa. Meskipun saya tidak menentang untuk menetapkan jenis pada istilah-istilah seperti itu dalam teori, perawatan yang berbeda pada @pragmaatau /*comment*/secara logis tidak konsisten.
FrankHB

-11

Kebanyakan tepatnya, sebuah pernyataan harus memiliki "efek samping" (yaitu menjadi keharusan ) dan ekspresi harus memiliki sebuah nilai tipe (yaitu bukan tipe bawah).

The jenis pernyataan adalah jenis unit, namun karena Menghentikan Unit teorema adalah fiksi sehingga katakanlah jenis bawah .


Voidbukan tipe dasarnya (bukan subtipe dari semua jenis yang mungkin). Itu ada dalam bahasa yang tidak memiliki sistem tipe suara sepenuhnya . Itu mungkin terdengar seperti pernyataan sombong, tetapi kelengkapan seperti anotasi varian sangat penting untuk menulis perangkat lunak yang dapat dikembangkan.

Mari kita lihat apa yang dikatakan Wikipedia tentang hal ini.

https://en.wikipedia.org/wiki/Statement_(computer_science)

Dalam pemrograman komputer, pernyataan adalah elemen mandiri terkecil dari bahasa pemrograman imperatif yang menyatakan beberapa tindakan yang harus dilakukan.

Banyak bahasa (misalnya C) membuat perbedaan antara pernyataan dan definisi, dengan pernyataan hanya berisi kode yang dapat dieksekusi dan definisi yang menyatakan pengidentifikasi, sementara ekspresi mengevaluasi hanya nilai.


5
Pernyataan tidak perlu memiliki efek samping. Misalnya, dalam python passadalah pernyataan. Ini adalah no-op, dan tidak mengevaluasi apa pun.
Matthew Schinckel

9
-1 Ini salah. Pernyataan tidak harus memiliki efek samping. Lihat bagian 1.5 dari Spesifikasi Bahasa C # . Tidak hanya itu tidak menentukan bahwa pernyataan harus memiliki efek samping, tetapi juga mencantumkan beberapa pernyataan yang tidak memiliki efek samping.
NullUserException

2
@NullUserException Saya membaca bagian itu. Pernyataan Deklarasi, Ekspresi, Pilihan, Iterasi, dan Langsung semua dapat menciptakan efek samping. Tetapi jika ada ekspresi RT, maka itu bukan pernyataan. Saya menyadari spesifikasinya menyamakan ekspresi dengan pernyataan, tetapi pertanyaan ini menanyakan perbedaan di antara mereka. Jadi pertanyaannya tidak memiliki jawaban, atau Anda mengambil C # spec secara harfiah. Jawaban yang terpilih adalah mencoba mengatakan apa yang saya lakukan. Tetapi "melakukan sesuatu" tidak ada artinya. "efek samping" adalah cara yang bermakna untuk mengatakan "melakukan sesuatu". Kita harus berpikir, tidak hanya memuntahkan.
Shelby Moore III

13
@ShelbyMooreIII Anda benar. Dokumentasi resmi salah . Marc Gravell dan Jon Skeet, yang mungkin adalah poster C # yang paling dihormati yang aktif di SO di luar Eric Lippert, salah . Saya, dan semua orang lain yang menurunkan Anda dan memberikan komentar menjelaskan posisi kami salah . Kamu benar. Anda jelas adalah satu-satunya orang yang tahu apa yang mereka bicarakan, karena Anda jauh lebih pintar daripada semua SO lainnya.
NullUserException

3
Mengetahui definisi konsep yang tepat seperti pernyataan, ekspresi, pemeran, konversi dll. Tidak berdampak pada 99,999% dari tugas pemrograman sehari-hari. Pikirkan tentang itu . Juga: kebanyakan orang tidak peduli dengan Haskell dan Scala.
NullUserException
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.