对于Scala,是否存在任何与LINQ(.NET)相似的类比?
答案 0 :(得分:55)
这取决于“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是
IQueryable
,LINQ-to-XML,LINQ-to-SQL,LINQ-to-Objects)在Scala中,就像几乎任何其他函数式语言一样(实际上也几乎是任何其他面向对象的语言),查询运算符只是标准集合API的一部分。在.NET中,它们有一些奇怪的名称,而在Scala中,它们具有与其他语言相同的标准名称:Select
是map
,Aggregate
是{{1} }(或reduce
),fold
为SelectMany
,flatMap
为Where
或filter
,withFilter
为{{1} }或orderBy
或sort
,还有sortBy
,sortWith
和zip
等等。因此,它负责规范和LINQ-to-Objects实现。 Scala的XML库还实现了集合API,它负责LINQ-to-XML。
SQL API没有内置到Scala中,但是有第三方API实现了集合API。
Scala还有针对这些API的专用语法,但与Haskell不同,后者试图使它们看起来像命令式C块和C#,它们试图使它们看起来像SQL查询,Scala尝试使它们看起来像{{1} }循环。它们被称为 take
comprehensions ,相当于C#的查询理解和Haskell的monad理解。 (它们也取代了C#的takeWhile
和生成器(for
))。
但如果确实想知道Scala中是否存在LINQ的类似物,那么首先必须具体说明“LINQ”究竟是什么意思。 (当然,如果你想知道它们是否“理智”,你也必须定义它。)
答案 1 :(得分:38)
Scala中提供了所有LINQ IEnumerable
扩展。例如:
的LINQ:
var total = orders
.Where(o => o.Customer == "myCustomer")
.SelectMany(o => o.OrderItems)
.Aggregate(0, (sum, current) => sum + current.Price * current.Count);
阶:
val total = orders
.filter(o => o.customer == "myCustomer")
.flatMap(o => o.orderItems)
.foldLeft(0)((s, c) => s + c.price * c.count)
答案 2 :(得分: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) }
答案 3 :(得分: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)
对于LINQ to SQL的模拟,最接近的可能是ScalaQuery。从文档中提取一个示例:
val q4c = for {
u <- Users
o <- Orders if o.userID is u.id
} yield u.first ~ o.orderID