Perché Scala ha il ritorno ma non si interrompe e continua

22

Scala non ha break o continue , quindi alcuni comportamenti del ciclo richiedono un po 'più di riflessione.

Termina un ciclo precoce richiede ricorsione di coda, eccezioni o scala.util.control.Breaks (che utilizza le eccezioni).

La logica di questo è che, come goto , sono costrutti di flusso che oscurano il flusso e possono essere realizzati in modi migliori, meno sorprendenti.

Ma sembra che quegli stessi argomenti potrebbero essere usati per return .

Perché Scala ha deliberatamente omesso break e continue , ma non return ?

    
posta Paul Draper 13.10.2014 - 17:04
fonte

2 risposte

16

Interrompi e continua:

In un discorso su Scala , Martin Odersky ha dato 3 motivi per non includere la pausa o continuare sulla diapositiva 22:

  • Sono un po 'imperativi; meglio usare molte funzioni più piccole.
  • Mostra come interagire con le chiusure.
  • Non sono necessari!

E poi dice: "Possiamo supportarli esclusivamente nelle biblioteche". Nella diapositiva 23, fornisce il codice che implementa break . Anche se non conosco abbastanza bene lo Scala per essere sicuro, sembra che il breve frammento di quella diapositiva sia tutto ciò che è necessario per implementare break , e che continue potrebbe essere implementato in un codice altrettanto breve.

Essere in grado di implementare cose come queste nelle librerie semplifica il linguaggio principale.

In "Programmazione in Scala, seconda edizione" di Martin Odersky, Lex Spoon e Bill Venners, viene fornita la seguente spiegazione:

You may have noticed that there has been no mention of break or continue. Scala leaves out these commands because they do not mesh well with function literals... It is clear what continue means inside a while loop, but what would it mean inside a function literal? ... There are many ways to program without break and continue, and if you take advantage of function literals, those alternatives can often be shorter than the original code.

Ritorno:

I ritorni potrebbero essere considerati un po 'imperativi nello stile, poiché return è un verbo, un comando per fare qualcosa. Ma possono anche essere visti in modo puramente funzionale / dichiarativo: definiscono quale sia il valore di ritorno della funzione (anche se, in una funzione con più ritorni, danno solo una definizione parziale).

Nello stesso libro, dicono quanto segue su return :

In the absence of any explicit return statement, a Scala method returns the last value computed by the method. The recommended style for methods is in fact to avoid having explicit, and especially multiple, return statements. Instead, think of each method as an expression that yields one value, which is returned.

I metodi terminano e restituiscono un valore, anche se non viene utilizzata un'istruzione return , quindi non ci possono essere problemi con le chiusure, poiché altrimenti le chiusure non funzionerebbero per un periodo.

Non ci può essere alcun problema di meshing con i letterali delle funzioni, poiché la funzione deve restituire comunque un valore.

    
risposta data 15.10.2014 - 02:10
fonte
0

Penso che le risposte precedenti rendano giustizia ai problemi di definizione della semantica per break o continue in modo linguistico per Scala, con contesti relativamente non vincolati.

Ho scritto una piccola libreria che definisce break e continue in un contesto più limitato: iterazione su sequenze via Scala per-comprensioni. Concentrandomi su quel contesto, credo che la semantica diventi non ambigua e facile da ragionare.

La libreria è disponibile qui: link

Ecco un semplice esempio di come appare nel codice:

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))
    
risposta data 08.03.2017 - 00:49
fonte

Leggi altre domande sui tag