ทำไมสกาล่าถึงกลับมา แต่ไม่หยุดพักและทำต่อไป


22

สกาล่าไม่มีbreakหรือcontinueดังนั้นพฤติกรรมวนรอบบางอย่างจึงใช้ความคิดอีกเล็กน้อย

การสิ้นสุดลูปก่อนกำหนดต้องใช้การเรียกซ้ำแบบหางข้อยกเว้นหรือscala.util.control.Breaks(ซึ่งใช้ข้อยกเว้น)

เหตุผลสำหรับเรื่องนี้ก็คือว่าgotoพวกเขาเป็นโครงสร้างการไหลที่ไม่ชัดเจนการไหลและสามารถทำได้ในวิธีที่ดีกว่าและน่าแปลกใจน้อยกว่า

returnแต่ดูเหมือนขัดแย้งกันเหล่านั้นสามารถนำมาใช้สำหรับ

เหตุใดสกาล่าจึงละเว้นbreakและcontinueไม่ทำเช่นนั้นreturn?


1
ฉันสามารถจินตนาการว่าผู้เขียนของภาษาพิจารณา recursion หางเป็นวิธีที่จะสร้างซ้ำ ฉันสามารถจินตนาการสิ่งนั้นและต้องการเครื่องจักรทำความสะอาดเพิ่มเติมบางอย่าง OTOH เป็นวิธีการยกเลิกฟังก์ชั่นอย่างเป็นระเบียบและเครื่องจักรล้างข้อมูลใด ๆ ก็มีอยู่แล้ว breakcontinuereturn
9000

1
มีbreakable { for { break; } }แต่ภายหลังและมีแนวโน้มที่จะห่างไกลจากที่มีประสิทธิภาพ
Joop Eggen

เพราะด้วยฟังก์ชั่นมันไม่มีเหตุผลอะไรเลย มันเหมือนกันในหลาม ทุกครั้งที่คุณใช้ for-loop กับ break คุณสามารถเขียนฟังก์ชันแทนที่ loop ของคุณในฟังก์ชันและใช้ return ฉันไม่สามารถคิดถึงสถานการณ์ที่นี่ไม่ใช่ความคิดที่ดีเกี่ยวกับรหัสสะอาด สำหรับประสิทธิภาพการทำความสะอาดอาจจะดีกว่า แต่ประสิทธิภาพไม่ได้มีความสำคัญสูงสุดในสกาล่า
valenterry

2
คำถามนี้ดูเหมือนว่าจะมีคำตอบที่นี่: stackoverflow.com/questions/3770989/…
Michael Shaw

3
@ PaulDraper: คำตอบสำหรับbreakและcontinueมีอยู่ในคำถามของคุณและในลิงก์ในคำถามของคุณ คำถามสำหรับreturnคือสิ่งที่คำถามที่ฉันเชื่อมโยงเกี่ยวกับและได้รับคำตอบอย่างน้อยที่สุดในคำตอบที่ได้รับการโหวตด้านบนยอมรับ หากทั้งสองคำตอบรวมกันไม่ตอบคำถามของคุณคุณอาจแก้ไขคำถามเพื่อให้ความกระจ่างได้
Michael Shaw

คำตอบ:


16

ทำลายและดำเนินการต่อ:

ในการพูดคุยเกี่ยวกับ Scalaมาร์ตินโอชสกี้ให้เหตุผล 3 ข้อที่ไม่รวมการหยุดพักหรือดำเนินการต่อในสไลด์ที่ 22

  • พวกเขามีความจำเป็นเล็กน้อย ควรใช้ฟังก์ชั่นเล็ก ๆ น้อย ๆ
  • ปัญหาวิธีการโต้ตอบกับการปิด
  • พวกเขาไม่ต้องการ!

จากนั้นเขาก็พูดว่า "เราสามารถช่วยเหลือพวกเขาได้อย่างหมดจดในห้องสมุด" บนสไลด์ที่ 23 breakเขาให้รหัสที่ดำเนินการ แม้ว่าฉันจะไม่รู้สกาล่าค่อนข้างดีพอที่จะแน่ใจ แต่ดูเหมือนว่าข้อมูลสั้น ๆ บนสไลด์นั้นเป็นสิ่งที่จำเป็นสำหรับการนำไปใช้breakและcontinueสามารถนำไปใช้ในโค้ดที่สั้นแบบเดียวกัน

ความสามารถในการใช้สิ่งต่าง ๆ ในห้องสมุดทำให้ภาษาหลักง่ายขึ้น

ใน 'การเขียนโปรแกรมใน Scala, Second Edition' โดย Martin Odersky, Lex Spoon และ Bill Venners คำอธิบายต่อไปนี้จะได้รับ:

คุณอาจสังเกตเห็นว่าได้มีการกล่าวถึงการไม่มีหรือbreak continueสกาล่าออกคำสั่งเหล่านี้เพราะพวกเขาไม่สอดคล้องกับตัวอักษรฟังก์ชั่น ... มันชัดเจนว่าอะไรคือสิ่งที่continueอยู่ภายในwhileวง แต่มันจะมีความหมายอะไรในตัวอักษรฟังก์ชั่น? ... มีหลายวิธีในการโปรแกรมโดยไม่ต้องbreakและcontinueถ้าคุณใช้ประโยชน์จากตัวอักษรฟังก์ชั่นทางเลือกเหล่านั้นมักจะสั้นกว่ารหัสต้นฉบับ

กลับ:

การส่งคืนอาจพิจารณาได้ว่ามีความจำเป็นอย่างยิ่งในสไตล์เนื่องจากการส่งคืนเป็นคำกริยาคำสั่งให้ทำบางสิ่งบางอย่าง แต่พวกเขายังสามารถเห็นได้ในวิธีการทำงาน / การประกาศอย่างหมดจด: พวกเขากำหนดสิ่งที่ค่าตอบแทนของฟังก์ชั่นคือ (แม้ว่าในฟังก์ชั่นที่มีผลตอบแทนหลายพวกเขาแต่ละคนให้คำจำกัดความบางส่วน)

ในหนังสือเล่มเดียวกันพวกเขาพูดเกี่ยวกับสิ่งต่อไปนี้return:

ในกรณีที่ไม่มีreturnคำสั่งที่ชัดเจนใด ๆวิธี Scala ส่งกลับค่าสุดท้ายที่คำนวณโดยวิธีการ รูปแบบที่แนะนำสำหรับวิธีการนั้นเป็นจริงเพื่อหลีกเลี่ยงการมีคำสั่งที่ชัดเจนและโดยเฉพาะอย่างยิ่งหลายreturnคำ ให้คิดว่าแต่ละวิธีแทนนิพจน์ที่ให้ค่าหนึ่งซึ่งจะถูกส่งคืนแทน

วิธีการสิ้นสุดและส่งกลับค่าแม้ว่าreturnจะไม่มีการใช้คำสั่งดังนั้นจึงไม่มีปัญหากับการปิดเนื่องจากการปิดไม่เช่นนั้นจะไม่ทำงาน

นอกจากนี้ยังไม่มีปัญหาในการผสานตัวอักษรฟังก์ชันเนื่องจากฟังก์ชันต้องส่งคืนค่าอยู่ดี


2
เกี่ยวกับการกลับมาดูเหมือนว่าจะมีอันตรายเล็กน้อย: tpolecat.github.io/2014/05/09/return.html
bbarker

0

ฉันคิดว่าคำตอบก่อนหน้านี้ทำเพื่อความยุติธรรมกับปัญหาของการกำหนดความหมายสำหรับbreakหรือcontinueในลักษณะที่กว้างภาษาสำหรับ Scala กับบริบทที่ค่อนข้าง จำกัด

ฉันเขียนห้องสมุดขนาดเล็กที่ให้คำจำกัดความbreakและcontinueในบริบทที่ จำกัด มากขึ้นนั่นคือวนซ้ำตามลำดับผ่าน Scala เพื่อความเข้าใจ โดยเน้นที่บริบทนั้นฉันเชื่อว่าความหมายนั้นไม่คลุมเครือและง่ายต่อการให้เหตุผล

ห้องสมุดมีให้บริการที่นี่: https://github.com/erikerlandson/breakable

นี่คือตัวอย่างง่ายๆของสิ่งที่ดูเหมือนว่าในรหัส:

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))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.