2012-12-30 14 views
19

Sono curioso - qual è il punto del tipo generico U nella dichiarazione del Traversable del metodo foreach?Qual è il punto del tipo generico in foreach?

def foreach[U](f: A => U): Unit 

Dal tipo di ritorno di Function1 è covariante, il motivo per cui non può che essere solo:

def foreach(f: A => Any): Unit 

?

+0

Non ho il tempo di fare un esempio, ma ho il forte sospetto che sia per consentire al tipo di inferenza di ignorare 'foreach' quando si tratta di inferire il tipo di ritorno di una funzione. Ma non conosco un caso dalla mia testa dove sarebbe importante (cioè che "Qualsiasi" non risulterebbe nella stessa inferenza). –

risposta

9

Non essendo Martin Odersky , Posso solo indovinare :-) Guardando lo Scaladoc di foreach, vedo questo:

/** Applies a function `f` to all elements of this $coll. 
    * 
    * @param f the function that is applied for its side-effect to every element. 
    *    The result of function `f` is discarded. 
    *    
    * @tparam U the type parameter describing the result of function `f`. 
    *    This result will always be ignored. Typically `U` is `Unit`, 
    *    but this is not necessary. 
    * 
    * @usecase def foreach(f: A => Unit): Unit 
    */ 

Quindi il tipo di ritorno di f non ha importanza e il suo risultato viene sempre scartato. Questo, per me, suggerisce che l'uso di un parametro di tipo generico qui per contrassegnare il tipo di ritorno è solo una sottigliezza della documentazione, dicendo "il tipo di ritorno può essere qualsiasi cosa, davvero qualsiasi cosa, ti piace". Considerando che un tipo di ritorno di Any può suggerire a (alcuni) lettori una sorta di limitazione ai tipi di funzione applicabili qui.

Un altro aspetto è che Scala è stato progettato in modo molto cosciente per essere generico da zero. Quindi - per me - usare un parametro di tipo generico è coerente con la filosofia generale della lingua, mentre usare Any - sebbene tecnicamente utilizzabile - sarebbe un approccio decisamente non generico che sarebbe in contrasto con il resto della lingua.

-5

Forse per consentire di ereditare da un Traversable, e fare qualche uso del valore di ritorno U da f: A => U?

trait TraversableWithHandler[+A, E <: Option[Throwable]] extends Traversable[A] { 
    override def foreach[U](f: A => U): Unit 
    def handleError(t: E) 
} 

Ad esempio in jQuery, ritorno di false dall'interno foreach è equivalente a break, qualsiasi valore diverso è un continue.

Use Case

breakable { 
    List(1,2,3).foreach(_ match { 
    case 1 => println("ok") 
    case 2 => 
     println("Sort of, soft interrupt?") 
     return false 
    case 3 => break 
    }) 
} 

Poiché il codice successivo (parallelo), non si rompe mai (soluzione Throwable stackless sembra non ideale in questo caso?):

import scala.util.control.Breaks._ 

breakable { 
    (0 to 100).toList.par.foreach(_ match { 
    case n if (n <= 50) => 
     println("#" * 100) 
     try { break } catch { 
     case t: Throwable => println("" + t); break 
     } 
    case n if (n > 50) => 
     println("" + n) 
    case _ => "ok" 
    }) 
} 
+0

-1: Dato che le eccezioni stackless sono usate comunque per il controllo del flusso in tali situazioni, e che avere un valore di ritorno formale non è di alcuna utilità in questo caso, questo è altamente improbabile. Inoltre, in realtà non mostri alcun caso d'uso. Non ho idea di come usare la firma sopra. –

+0

Ciò sarebbe in contrasto con lo Scaladoc che dice: "Il risultato della funzione' f' viene scartato. " –

+5

Questa risposta non è solo sbagliata, è potenzialmente molto confusa. Hai appena ribattezzato il parametro type in modo che ombreggia 'scala.Boolean'-non hai sicuramente vincolato in qualche modo il metodo dichiarato in' Traversable'. –

Problemi correlati