2010-09-24 9 views
46

Esistono analoghi sane a LINQ (.NET) per Scala?analoghi LINQ in Scala?

+3

Metodo specifico LINQ abbinato alla Scala equivalente: http://stackoverflow.com/questions/8104846/chart-of-ienumerable-linq-equivalents-in-scala –

+0

LINQ per Scala (completo API) e supporto per l'esecuzione differita: https://github.com/nicholas22/propelS – Scooterville

+2

Vedi anche: http://stackoverflow.com/a/8106548/192247. Potrebbe essere utile. – missingfaktor

risposta

54

dipende da cosa esattamente si intende per "LINQ". LINQ è molte cose.

La risposta più ovvia sarebbe: basta usare la porta .NET di Scala. Ti dà accesso nativo completo a tutto in .NET, che ovviamente include LINQ.

Sfortunatamente, la porta .NET di Scala è stata eliminata un paio di anni fa. Fortunatamente, è stato ripreso un paio di mesi fa, con finanziamenti ufficiali direttamente da Microsoft, non meno. Ci si può aspettare un rilascio a volte nel periodo di tempo 2011/2012.

In ogni caso, che cos'è LINQ?

Un paio di funzionalità aggiunte a .NET e in particolare C# e VB.NET per LINQ. Non sono tecnicamente parte di LINQ, ma sono prerequisiti necessari: inferenza di tipo, tipi anonimi (strutturali), espressioni lambda, tipi di funzione (Func<T...> e Action<T...>) e alberi di espressione. Tutti questi sono stati in Scala per molto tempo, la maggior parte sono stati lì per sempre.

Anche non direttamente parte di LINQ, ma in C#, le espressioni di query LINQ possono essere utilizzate per generare XML, per emulare i valori letterali XML di VB.NET. Scala ha letterali XML, come VB.NET.

Più specificamente, LINQ è

  • una specifica per un insieme di operatori di query standard
  • una serie di implementazioni per gli operatori (IQueryable, LINQ to XML, LINQ to SQL, LINQ to Objects)
  • una sintassi incorporato incorporato per LINQ comprensioni di query
  • una monade

In Scala, come in praticamente qualsiasi altro linguaggio funzionale (e in effetti anche praticamente qualsiasi altro linguaggio orientato agli oggetti), gli operatori di query sono semplicemente parte dell'API delle collezioni standard. In .NET, hanno un po nomi strani bit, mentre in Scala, hanno gli stessi nomi standard hanno in altre lingue: Select è map, Aggregate è reduce (o fold), SelectMany è flatMap, Where è filter o withFilter, orderBy è sort o sortBy o sortWith e ci sono zip, take e takeWhile e così via. Quindi, questo si occupa sia della specifica che dell'implementazione LINQ-to-Objects. Le librerie XML di Scala implementano anche le API delle raccolte, che si occupano di LINQ-to-XML.

Le API SQL non sono integrate in Scala, ma esistono API di terze parti che implementano l'API di raccolta.

Scala ha anche una sintassi specializzata per tali API, ma a differenza di Haskell, che tenta di farli apparire come blocchi C imperativi e C#, che tenta di farli sembrare query SQL, Scala cerca di farli apparire come i loop for. Si chiamano for comprehensions e sono l'equivalente delle query query di C# e le comprensioni di hashing di Haskell. (Sostituiscono anche i C foreach e i generatori (yield return)).

Ma se si in realtà si desidera sapere se ci sono o meno analoghi per LINQ in Scala, sarà prima necessario specificare cosa intendi esattamente per "LINQ". (E, naturalmente, se volete sapere se sono "sane", si dovrà definire anche questo.)

+19

La parte più utile della risposta è "Select is map, Where is filter o withFilter, orderBy è sort o sortBy or sortWith , ... ". Mi manca solo Count(), First(), FirstOrDefault(). –

+11

'size',' head', 'headOption.getOrElse'. Questi sono tutti in scala.collection.Iterable (http://www.scala-lang.org/api/current/scala/collection/Iterable.html – stevej

+5

Uno * enorme * vantaggio di LINQ è che supporta la decostruzione in Expression Trees che consente a tutta la magia LINQ2SQL di "funzionare". Sintassi a parte, questo livello di integrazione dell'albero delle espressioni non è attualmente disponibile in Scala, quindi tutti i "provider corrispondenti" devono effettivamente fornire la propria gestione AST senza questo livello di astrazione. –

8

Esistono molte situazioni in Scala in cui è possibile utilizzare i costrutti monadici come una sorta di linguaggio di query.

Ad esempio, per eseguire query XML (in questo caso, estraendo gli URL dai collegamenti in alcuni XHTML):

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

Per un analogo di LINQ to SQL, la cosa più vicina è probabilmente ScalaQuery. Per sollevare un esempio a destra, fuori i documenti:

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

Tutte le estensioni LINQ IEnumerable sono disponibili in Scala. Per esempio:

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 ed esiste. http://www.scala-lang.org/docu/files/collections-api/collections.html – onof

10

Slick

è una moderna libreria di query di database e l'accesso per 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) }