【问题标题】:LINQ analogues in Scala?Scala中的LINQ类似物?
【发布时间】:2011-04-16 16:06:54
【问题描述】:

Scala 中是否存在与 LINQ (.NET) 类似的合理方法?

【问题讨论】:

标签: linq scala


【解决方案1】:

流畅

是 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) }

【讨论】:

    【解决方案2】:

    所有 LINQ IEnumerable 扩展都在 Scala 中可用。例如:

    林克:

    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)
    

    【讨论】:

    【解决方案3】:

    这取决于您所说的“LINQ”到底是什么意思。 LINQ 有很多东西。

    最明显的答案是:只需使用 Scala 的 .NET 端口即可。它使您可以完全本地访问 .NET 中的所有内容,其中显然包括 LINQ。

    不幸的是,Scala 的 .NET 端口在几年前就被放弃了。幸运的是,几个月前它又被重新拾起,直接来自微软的官方资金也不少。您可以期待在 2011/2012 年的某个时间发布。

    那么,什么是 LINQ?

    添加到 .NET 的一些特性,特别是 C# 和 VB.NET LINQ。它们在技术上不是 LINQ 的一部分,但它们是必要的先决条件:类型推断、匿名(结构)类型、lambda 表达式、函数类型(Func&lt;T...&gt;Action&lt;T...&gt;)和表达式树。所有这些都在 Scala 中存在了很长时间,其中大部分一直存在。

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

    更具体地说,LINQ 是

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

    在 Scala 中,与几乎所有其他函数式语言(实际上也几乎所有其他面向对象语言)一样,查询运算符只是标准集合 API 的一部分。在 .NET 中,它们的名称有点奇怪,而在 Scala 中,它们具有与其他语言相同的标准名称:SelectmapAggregatereduce(或 fold), SelectManyflatMapWherefilterwithFilterorderBysortsortBysortWith,还有zip 和@9864341@ 和@9867654339@等等。因此,这需要注意规范和 LINQ-to-Objects 实现。 Scala 的 XML 库还实现了集合 API,它负责 LINQ-to-XML。

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

    Scala 还为这些 API 提供了专门的语法,但与 Haskell 不同,Haskell 试图让它们看起来像命令式 C 块,而 C# 试图让它们看起来像 SQL 查询,Scala 试图让它们看起来像 for 循环.它们被称为 for comprehensions,相当于 C# 的查询理解和 Haskell 的 monad 理解。 (它们还替换了 C# 的 foreach 和生成器 (yield return)。

    但如果您真的想知道 Scala 中是否有 LINQ 的类似物,您首先必须具体说明“LINQ”的确切含义。 (当然,如果你想知道他们是否“理智”,你也必须定义它。)

    【讨论】:

    • 答案中最有用的部分是“Select 是 map,Where 是 filter 或 withFilter,orderBy 是 sort 或 sortBy 或 sortWith,...”。我只是缺少 Count()、First()、FirstOrDefault()。
    • size, head, headOption.getOrElse.这些都在scala.collection.Iterable
    • LINQ 的一个巨大 优势是它支持解构为表达式树,这允许所有 LINQ2SQL 魔法“正常工作”。除了语法,这种级别的表达式树集成目前在 Scala 中不可用,因此所有“相应的提供者”必须有效地提供自己的 AST 处理,而不需要这种抽象级别。
    • @pst:是的,您目前可以使用 VCR 类型的 Dynamic 对象来执行此操作,该对象捕获所有方法调用,但这非常脆弱且相当复杂。让我们看看虚拟化的 Scala 和宏带来了什么。
    • 任何想法 Scala 的 .NET 端口发生了什么?停产了吗?
    【解决方案4】:

    在 Scala 中有很多情况下,您可以使用一元结构作为一种查询语言。

    例如,查询 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
    

    【讨论】:

      猜你喜欢
      • 2011-04-14
      • 1970-01-01
      • 2011-04-29
      • 2011-12-27
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多