2014-07-07 12 views
6

breakout ist schön, aber zu ausführlich:Alternative zu breakout, die weniger ausführlich ist

List(1, 2, 3).map{i => (i * 2, i/2.0, i.toString)}(breakOut) : Array[(Int, Double, String)] 

Ich will nicht den Elementtyp angeben. Ich möchte so etwas wie:

List(1, 2, 3).map{i => (i * 2, i/2.0, i.toString)}(build[Array]) 

ich leicht einen buildArray schreiben kann, aber dann würde ich brauche eine buildSet, Buildlist, etc. So möchte ich etwas generisch.

Extrapunkte (;-)), wenn Sie können es für Karte funktioniert (mit dem gleichen Namen build, build2 oder BuildMap nicht)

+1

[Dies ist] (http://pastebin.com/rsmFtqdt) nicht was Sie wollen, aber ich denke, es ist das Beste, was Sie bekommen können. Dies funktioniert nicht für 'String' oder' Map'. – senia

+0

Ja, das ist was ich wollte. Ich habe das gleiche gemacht, aber die generischen Parameter gemischt (T in def und A in code) und konnte es nicht aus dem Compiler-Fehler herausfinden. – IttayD

+1

@senia Vielleicht eine Antwort machen? –

Antwort

4

Dies wird für String oder Map nicht funktionieren. Auch dieser Code erfordert scala.language.higherKinds:

import collection.generic.CanBuildFrom 
import collection.breakOut 

class Build[To[_]] 

def build[To[_]] = new Build[To] 

implicit def buildToCbf[From, T, To[_]](b: Build[To]) 
             (implicit cbf: CanBuildFrom[Nothing,T,To[T]]): CanBuildFrom[From,T,To[T]] = 
    collection.breakOut 

List(1, 2, 3).map{i => (i * 2, i/2.0, i.toString)}(build[Array]) 
//res0: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3)) 
1

Senia Lösung ist groß. Leider, wie er erwähnt hat, funktioniert das nicht für Map noch String. Hier ist eine weitere Alternative (basierend auf seiner Lösung), das tut:

import collection.generic.CanBuildFrom 
import collection.breakOut 

class Build[To] 

def build[TargetSuperType] = new Build[TargetSuperType] 

implicit def buildToCbf[From, T, TargetSuperType, To<:TargetSuperType](b: Build[TargetSuperType]) 
             (implicit cbf: CanBuildFrom[Nothing,T,To]): CanBuildFrom[From,T,To] = 
    collection.breakOut 

List(1, 2, 3).map{i => (i * 2, i/2.0, i.toString)}(build[Array[_]]) 
//res0: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3)) 

List(1, 2, 3).map{i => (i * 2, i.toString)}(build[Map[_,_]]) 
//res1: scala.collection.immutable.Map[Int,String] = Map(2 -> 1, 4 -> 2, 6 -> 3) 

List('a', 'b', 'c').map(_.toUpper)(build[String]) 
//res2: String = ABC 

Dieses kleine ausführlicher ist, weil Sie jetzt einfach nicht build[Array] tun, aber build[Array[_]]. Im Gegenzug können Sie unabhängig von der Anzahl der Typargumente eine beliebige Zielobjektgruppe angeben (z. B. Map und String).

Plus können Sie immer noch voll explizit sein (ähnlich wie bei breakOut verwenden) wenn Sie wählen:

scala> List(1, 2, 3).map{i => (i * 2, i/2.0, i.toString)}(build[Array[(Int, Double, String)]]) 
res3: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3)) 

, dass alle mit der gleichen Syntax (in anderen Worten, mit dem gleichen Namen build, wie gewünscht)

Verwandte Themen