2010-09-24 4 views
46

Existe-t-il des analogues sains à LINQ (.NET) pour Scala?Analogues LINQ dans Scala?

+3

méthode LINQ spécifique adaptée à l'équivalent de rampe: http://stackoverflow.com/questions/8104846/chart-of-ienumerable-linq-equivalents-in-scala –

+0

LINQ pour Scala (full API) et support de l'exécution différée: https://github.com/nicholas22/propelS – Scooterville

+2

Voir aussi: http://stackoverflow.com/a/8106548/192247. Cela pourrait être utile. – missingfaktor

Répondre

54

Cela dépend de ce que vous exactement par "LINQ". LINQ est beaucoup de choses.

La réponse la plus évidente serait: il suffit d'utiliser le port .NET de Scala. Il vous donne un accès natif complet à tout ce qui est dans .NET, ce qui inclut évidemment LINQ.

Malheureusement, le port .NET de Scala a été supprimé il y a quelques années. Heureusement, il a été repris il y a quelques mois, avec un financement officiel directement de Microsoft. Vous pouvez vous attendre à une sortie dans le calendrier 2011/2012.

Quoi qu'il en soit, qu'est-ce que LINQ?

Un couple de fonctionnalités ajoutées à .NET et en particulier C# et VB.NET pour LINQ. Ils ne font pas techniquement partie de LINQ, mais sont des pré-requis nécessaires: inférence de type, types (structuraux) anonymes, expressions lambda, types de fonctions (Func<T...> et Action<T...>) et arbres d'expressions. Tout cela a été à Scala depuis longtemps, la plupart ont été là pour toujours.

De même, elles ne font pas directement partie de LINQ, mais en C#, les expressions de requête LINQ peuvent être utilisées pour générer du code XML, afin d'émuler les littéraux XML de VB.NET. Scala a des littéraux XML, comme VB.NET.

Plus précisément, LINQ est

  • une spécification pour un ensemble d'opérateurs de requête standard
  • un ensemble de mises en œuvre pour les opérateurs (c.-à-IQueryable, LINQ à XML, LINQ to SQL, LINQ-to-objets)
  • une syntaxe embedded intégrée pour la requête LINQ compréhensions
  • une monade

Dans Scala, comme dans presque tous les autres langages fonctionnels (et en fait aussi à peu près tout autre langage orienté objet), les opérateurs de requête font simplement partie de l'API des collections standard. Dans .NET, ils ont un peu des noms bizarres, alors que dans Scala, ils ont les mêmes noms standard qu'ils ont dans d'autres langues: Select est map, Aggregate est reduce (ou fold), SelectMany est flatMap, Where est filter ou withFilter, orderBy est sort ou sortBy ou sortWith, et il y a zip, take et takeWhile et ainsi de suite. Ainsi, cela prend en compte à la fois la spécification et l'implémentation LINQ-to-Objects. Les bibliothèques XML de Scala implémentent également les API de collections, qui prennent en charge LINQ-to-XML.

Les API SQL ne sont pas intégrées à Scala, mais des API tierces implémentent l'API de collecte. Scala a également une syntaxe spécialisée pour ces API, mais contrairement à Haskell, qui essaie de les faire ressembler à des blocs C impératifs et C#, qui essaie de les faire ressembler à des requêtes SQL, Scala essaie de les faire ressembler à des boucles for. Ils sont appelés for et sont l'équivalent de la compréhension des requêtes de C# et des compréhensions de monad de Haskell. (Ils remplacent aussi les foreach de C# et les générateurs (yield return)).

Mais si vous vraiment voulez savoir s'il y a des produits analogues pour LINQ dans Scala, vous devez d'abord spécifier exactement ce que vous voulez dire par "LINQ". (Et bien sûr, si vous voulez savoir si elles sont « sain d'esprit », vous devez définir cela aussi.)

+19

La partie la plus utile de la réponse est "Select is map, Où est filter ou withFilter, orderBy est sort ou sortBy ou sortWith , ... ". Il me manque juste Count(), First(), FirstOrDefault(). –

+11

'size',' head', 'headOption.getOrElse'.Ces sont tous dans [scala.collection.Iterable] (http://www.scala-lang.org/api/current/scala/collection/Iterable.html – stevej

+5

Un avantage * énorme * LINQ est qu'il supporte la déconstruction en Expression Trees qui permet à toute la magie LINQ2SQL de "fonctionner". Syntaxe mise à part, ce niveau d'intégration de l'arbre d'expression n'est actuellement pas disponible dans Scala, de sorte que tous les "fournisseurs correspondants" doivent effectivement fournir leur propre gestion AST sans ce niveau d'abstraction. –

8

Il existe de nombreuses situations dans Scala où vous pouvez utiliser des constructions monadiques comme une sorte de langage de requête.

Par exemple, pour interroger XML (dans ce cas, l'extraction des URL à partir de liens dans certains XHTML):

def findURLs(xml: NodeSeq): Seq[URL] = 
    for { 
    a <- xml \\ "a" 
    href <- a attribute "href" 
    url <- href.text 
    } yield URL(url) 

Pour un analogue de LINQ to SQL, la chose la plus proche est probablement ScalaQuery. Pour soulever un bon exemple de la documentation:

val q4c = for { 
    u <- Users 
    o <- Orders if o.userID is u.id 
} yield u.first ~ o.orderID 
37

Toutes les extensions LINQ IEnumerable sont disponibles à Scala. Par exemple:

Linq:

var total = orders 
     .Where(o => o.Customer == "myCustomer") 
     .SelectMany(o => o.OrderItems) 
     .Aggregate(0, (sum, current) => sum + current.Price * current.Count); 

scala:

val total = orders 
     .filter(o => o.customer == "myCustomer") 
     .flatMap(o => o.orderItems) 
     .foldLeft(0)((s, c) => s + c.price * c.count) 
+0

@oleksii forAll et existe. http://www.scala-lang.org/docu/files/collections-api/collections.html – onof

10

Slick

est une bibliothèque de requête de base de données moderne et accès Scala. (http://slick.typesafe.com/)

@table("COFFEES") case class Coffee(
    @column("COF_NAME") name: String, 
    @column("SUP_ID") supID: Int, 
    @column("PRICE") price: Double 
) 
val coffees = Queryable[Coffee] 


// for inserts use lifted embedding or SQL 
val l = for { 
    c <- coffees if c.supID == 101 
    //      ^comparing Int to Int! 
} yield (c.name, c.price) 


backend.result(l, session) 
.foreach { case (n, p) => println(n + ": " + p) }