Scala中的LINQ类似物?

46 linq scala

是否存在针对Scala的任何理智的LINQ(.NET)类似物?

Jör*_*tag 56

这取决于"LINQ"究竟是什么意思.LINQ有很多东西.

最明显的答案是:只使用Scala的.NET端口.它为您提供对.NET中所有内容的完全本机访问,其中显然包括LINQ.

不幸的是,几年前Scala的.NET端口被丢弃了.幸运的是,它在几个月前再次被提起,直接来自微软的官方资金也不少.您可以期待在2011/2012年的某个时间段内发布.

无论如何,什么是LINQ?

添加到.NET的一些功能,特别是用于 LINQ的C#和VB.NET .它们在技术上不是LINQ的一部分,但它们是必要的先决条件:类型推断,匿名(结构)类型,lambda表达式,函数类型(Func<T...>Action<T...>)和表达式树.所有这些都已经在Scala很长一段时间了,大多数都在那里永远存在.

也不是LINQ的直接部分,但在C#中,LINQ查询表达式可用于生成XML,以模拟VB.NET的XML文字.Scala具有XML文字,如VB.NET.

更具体地说,LINQ是

  • 一组标准查询运算符的规范
  • 这些运算符的一组实现(即IQueryableLINQ-to-XML,LINQ-to-SQL,LINQ-to-Objects)
  • LINQ查询理解的内置嵌入式语法
  • 一个单子

在Scala中,就像几乎任何其他函数式语言一样(实际上也是几乎任何其他面向对象的语言),查询运算符只是标准集合API的一部分.在.NET中,它们有一些奇怪的名称,而在Scala中,它们具有与其他语言相同的标准名称:Selectis map,Aggregateis reduce(or fold),SelectManyis flatMap,Whereis filteror withFilter,orderByis sortor sortByor sortWith,and are zip,takeand,takeWhileand等等.因此,它负责规范和LINQ-to-Objects实现.Scala的XML库还实现了集合API,它负责LINQ-to-XML.

SQL API没有内置到Scala中,但是有第三方API实现了集合API.

Scala还具有针对这些API的专用语法,但与Haskell不同,后者试图使它们看起来像命令式C块和C#,它们试图使它们看起来像SQL查询,Scala尝试使它们看起来像for循环.它们被称为for理解,相当于C#的查询理解和Haskell的monad理解.(它们也取代了C#foreach和generator(yield return)).

但是,如果您真的想知道Scala中是否存在LINQ的类似物,那么您首先必须具体说明"LINQ"究竟是什么意思.(当然,如果你想知道他们是否"理智",你也必须定义它.)

  • 答案中最有用的部分是"Select is map,Where is filter or withFilter,orderBy is sort or sortBy or sortWith,...".我只是缺少Count(),First(),FirstOrDefault(). (20认同)
  • `size`,`head`,`headOption.getOrElse`.这些都在[scala.collection.Iterable]中(http://www.scala-lang.org/api/current/scala/collection/Iterable.html) (11认同)
  • LINQ的一个巨大优势是它支持解构为Expression Trees,它允许所有LINQ2SQL魔法"正常工作".除了语法之外,Scala当前不提供这种级别的表达式树集成,因此所有"相应的提供者"必须在没有这种抽象级别的情况下有效地提供自己的AST处理. (5认同)

ono*_*nof 39

IEnumerableScala中提供了所有LINQ 扩展.例如:

LINQ:

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

斯卡拉:

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


Miu*_*ler 10

华而不实的

是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) }
Run Code Online (Sandbox Code Playgroud)


Ben*_*mes 8

在Scala中有许多情况可以使用monadic结构作为一种查询语言.

例如,要查询XML(在这种情况下,从某些XHTML中的链接中提取URL):

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

对于LINQ to SQL的模拟,最接近的可能就是ScalaQuery.从文档中提取一个示例:

val q4c = for {
  u <- Users
  o <- Orders if o.userID is u.id
} yield u.first ~ o.orderID
Run Code Online (Sandbox Code Playgroud)