Mengapa Scala harus kembali tetapi tidak istirahat dan melanjutkan

22

Scala tidak memiliki breakatau continue, sehingga beberapa perilaku berulang membutuhkan lebih banyak pemikiran.

Mengakhiri loop lebih awal membutuhkan rekursi ekor, pengecualian, atau scala.util.control.Breaks(yang menggunakan pengecualian).

Alasan untuk ini adalah bahwa, seperti goto, mereka adalah konstruksi aliran yang mengaburkan aliran, dan dapat dicapai dengan cara yang lebih baik, tidak terlalu mengejutkan.

Tapi sepertinya argumen yang sama bisa digunakan untuk itu return.

Mengapa Scala sengaja menghilangkan breakdan continue, tetapi tidak return?

Paul Draper
sumber
1
Saya bisa membayangkan bahwa penulis bahasa menganggap rekursi ekor sebagai yang cara untuk membangun iterasi. Saya bisa membayangkan itu breakdan continuemembutuhkan beberapa mesin pembersihan tambahan. OTOH returnadalah cara untuk menghentikan fungsi secara tertib, dan semua mesin pembersihan sudah ada di sana.
9000
1
Hanya ada breakable { for { break; } }renungan, dan kemungkinan jauh dari efisien.
Joop Eggen
Karena dengan fungsi sebenarnya tidak ada alasan untuk itu. Itu sama dengan python. Setiap kali Anda menggunakan for-loop dengan break, Anda bisa menulis fungsi, meletakkan loop Anda ke dalam fungsi dan menggunakan return. Saya tidak bisa memikirkan situasi di mana ini bukan ide yang baik tentang kode bersih. Untuk kinerja, clean mungkin lebih baik, tetapi kinerja tidak memiliki prioritas tertinggi dalam scala.
valenterri
2
Pertanyaan ini sepertinya memiliki jawaban di sini: stackoverflow.com/questions/3770989/…
Michael Shaw
3
@ PaulDraper: Jawaban untuk breakdan continueterkandung dalam pertanyaan Anda dan di tautan dalam pertanyaan Anda. Pertanyaannya returnadalah persis apa pertanyaan yang saya tautkan, dan dijawab, setidaknya dalam jawaban yang dipilih, yang diterima. Jika kedua jawaban tersebut tidak menjawab pertanyaan Anda, mungkin Anda dapat mengedit pertanyaan untuk menjelaskannya.
Michael Shaw

Jawaban:

16

Istirahat dan Lanjutkan:

Dalam sebuah pembicaraan tentang Scala , Martin Odersky memberi 3 alasan untuk tidak memasukkan istirahat atau melanjutkan slide 22:

  • Mereka sedikit penting; lebih baik gunakan banyak fungsi yang lebih kecil.
  • Masalah cara berinteraksi dengan penutupan.
  • Mereka tidak dibutuhkan!

Dan dia kemudian berkata, "Kita dapat mendukung mereka sepenuhnya di perpustakaan." Pada slide 23, ia memberikan kode yang mengimplementasikanbreak . Meskipun saya tidak begitu tahu Scala cukup baik untuk memastikan, sepertinya potongan pendek pada slide itu adalah semua yang diperlukan untuk mengimplementasikan break, dan itu continuedapat diimplementasikan dalam kode yang sama pendeknya.

Mampu menerapkan hal-hal seperti ini di perpustakaan menyederhanakan bahasa inti.

Dalam 'Pemrograman dalam Scala, Edisi Kedua', oleh Martin Odersky, Lex Spoon, dan Bill Venners, penjelasan berikut diberikan:

Anda mungkin telah memperhatikan bahwa belum ada breakatau continue. Scala meninggalkan perintah-perintah ini karena mereka tidak cocok dengan fungsi literal ... Jelas apa continueartinya di dalam whileloop, tetapi apa artinya di dalam fungsi literal? ... Ada banyak cara untuk memprogram tanpa breakdancontinue , dan jika Anda memanfaatkan fungsi literal, alternatif tersebut seringkali lebih pendek dari kode aslinya.

Kembali:

Pengembalian dapat dianggap sebagai keharusan dalam gaya, karena pengembalian adalah kata kerja, perintah untuk melakukan sesuatu. Tetapi mereka juga dapat dilihat secara murni fungsional / deklaratif: mereka mendefinisikan apa nilai balik dari fungsi tersebut (bahkan jika, dalam suatu fungsi dengan banyak pengembalian, mereka masing-masing hanya memberikan definisi parsial).

Dalam buku yang sama, mereka mengatakan hal berikut tentang return:

Dengan tidak adanya returnpernyataan eksplisit , metode Scala mengembalikan nilai terakhir yang dihitung oleh metode. Gaya yang direkomendasikan untuk metode sebenarnya adalah untuk menghindari returnpernyataan yang eksplisit, dan khususnya banyak ,. Sebaliknya, pikirkan setiap metode sebagai ekspresi yang menghasilkan satu nilai, yang dikembalikan.

Metode mengakhiri dan mengembalikan nilai, bahkan jika a return pernyataan tidak digunakan, sehingga tidak ada masalah dengan penutupan, karena jika tidak, penutupan tidak akan bekerja.

Juga tidak ada masalah menyatu dengan fungsi literal, karena fungsi tetap harus mengembalikan nilai.

Michael Shaw
sumber
2
Mengenai kembali, tampaknya ada beberapa bahaya ringan: tpolecat.github.io/2014/05/09/return.html
bbarker
0

Saya pikir jawaban sebelumnya adil untuk masalah mendefinisikan semantik untuk breakataucontinue dalam bahasa untuk Scala, dengan konteks yang relatif tidak dibatasi.

Saya menulis perpustakaan kecil yang mendefinisikan breakdancontinue dalam konteks yang lebih terbatas: iterasi atas urutan melalui Scala untuk-pemahaman. Dengan berfokus pada konteks itu, saya percaya bahwa semantik menjadi tidak ambigu dan mudah dipikirkan.

Perpustakaan tersedia di sini: https://github.com/erikerlandson/breakable

Berikut ini contoh sederhana dari apa yang tampak dalam kode:

scala> import com.manyangled.breakable._
import com.manyangled.breakable._

scala> val bkb2 = for {
     |   (x, xLab) <- Stream.from(0).breakable   // create breakable sequence with a method
     |   (y, yLab) <- breakable(Stream.from(0))  // create with a function
     |   if (x % 2 == 1) continue(xLab)          // continue to next in outer "x" loop
     |   if (y % 2 == 0) continue(yLab)          // continue to next in inner "y" loop
     |   if (x > 10) break(xLab)                 // break the outer "x" loop
     |   if (y > x) break(yLab)                  // break the inner "y" loop
     | } yield (x, y)
bkb2: com.manyangled.breakable.Breakable[(Int, Int)] = com.manyangled.breakable.Breakable@34dc53d2

scala> bkb2.toVector
res0: Vector[(Int, Int)] = Vector((2,1), (4,1), (4,3), (6,1), (6,3), (6,5), (8,1), (8,3), (8,5), (8,7), (10,1), (10,3), (10,5), (10,7), (10,9))
mis
sumber