Чому Скала повертається, але не ламається і продовжує


22

У Scala немає breakабо continue, отже, певна поведінка циклу вимагає трохи більше мислення.

Закінчення циклу достроково вимагає рекурсії хвоста, винятку або scala.util.control.Breaks(що використовує винятки).

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

Але, схоже, ці самі аргументи можна було б використати і для return.

Чому Скала свідомо опустив breakі continue, але ні return?


1
Я можу собі уявити , що автори мови вважають хвостову рекурсію , як на шляху побудови ітерації. Я можу це уявити breakі мені continueпотрібна додаткова техніка очищення. OTOH return- це спосіб упорядкувати припинення функції, і будь-яка техніка для очищення вже є.
9000

1
Існує breakable { for { break; } }лише думка і, мабуть, далеко не ефективна.
Joop Eggen

Тому що з функціями насправді немає причини для цього. Те саме в python. Кожен раз, коли ви використовуєте цикл for-циклу з перервою, ви можете замість цього написати функцію, ввести цикл у функцію та використовувати return. Я не можу придумати ситуацію, коли це не є хорошою ідеєю щодо чистого коду. Для продуктивності чистіше може бути краще, але продуктивність не має найвищого пріоритету в масштабі.
valenterry

2
Схоже, на це запитання є відповідь тут: stackoverflow.com/questions/3770989/…
Michael Shaw

3
@PaulDraper: Відповідь breakі continueміститься у вашому запитанні та у посиланні у вашому запитанні. Питання - returnце саме те питання, про яке я пов’язував, і на нього було відповідено, принаймні, у голосованій прийнятій відповіді. Якщо дві відповіді, складені разом, не відповідають на ваше запитання, можливо, ви можете відредагувати це питання, щоб уточнити його.
Майкл Шоу

Відповіді:


16

Перерва та продовження:

У розмові про Scala Мартін Одерський дав 3 причини не включати перерву чи продовжувати на слайді 22:

  • Вони трохи імперативні; краще використовувати багато менших функцій.
  • Питання, як взаємодіяти із закриттями.
  • Вони не потрібні!

Потім він каже: "Ми можемо підтримувати їх суто в бібліотеках". На слайді 23 він дає код, який реалізує break. Хоча я не дуже добре знаю Scala, щоб бути впевненим, схоже, що короткий фрагмент на цьому слайді - це все, що потрібно для реалізації break, і це continueможе бути реалізовано в коді, який так само короткий.

Можливість реалізувати подібні речі в бібліотеках спрощує основну мову.

У "Програмуванні в Scala, друге видання", Мартіна Одерського, Lex Spoon та Білла Веннерса подано таке пояснення:

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

Повернення:

Повернення можна вважати трохи імперативним за стилем, оскільки return - це дієслово, команда робити щось. Але їх також можна побачити суто функціональним / декларативним способом: вони визначають, що таке повернене значення функції (навіть якщо у функції з кількома поверненнями вони дають лише часткове визначення).

У цій же книзі вони говорять про return:

За відсутності явного returnтвердження, метод Scala повертає останнє значення, обчислене методом. Рекомендований стиль методів насправді не дозволяє мати явні, а особливо множинні, returnзаяви. Натомість розгляньте кожен метод як вираз, який дає одне значення, яке повертається.

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

Також не може бути проблем зв'язатись з функціональними літералами, оскільки функція повинна повертати значення.


2
Щодо повернення, то, схоже, є деякі легкі небезпеки: tpolecat.github.io/2014/05/09/return.html
bbarker

0

Я думаю, що попередні відповіді справедливо вирішують проблеми визначення семантики для Скали breakабо continueв мовній манері з відносно необмеженими контекстами.

Я написав невелику бібліотеку, яка визначає 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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.