【问题标题】:Weird currying of Update function of MongoCollection class of Casbah Mongo driverCasbah Mongo 驱动程序的 MongoCollection 类的 Update 函数的奇怪柯里化
【发布时间】:2015-06-12 21:19:23
【问题描述】:

如您所知,casbah mongodb 驱动程序具有这样的更新功能:

def update [A, B] (q: A, o: B)(implicit arg0: (A) ⇒ DBObject, arg1: (B) ⇒ DBObject) : WriteResult

我想我理解 scala 的柯里化概念。但是,据我所知,这个更新功能应该是这样使用的:

collection.update(MongoDBObject(...), MongoDBObject(...))

这让我很困惑。由于我没有填写更新方法的第二个参数列表,我认为上面的表达式会返回一个类似的函数:

(implicit arg0: (A) ⇒ DBObject, arg1: (B) ⇒ DBObject) => WriteResult

然而事实并非如此。是因为第二个函数参数列表中参数的隐式定义吗?

【问题讨论】:

  • 如果你有一个A => DBObject 类型的隐式值和B => DBObject 的隐式值,那么在调用update 时会应用这些值。不过,如果您只想部分应用该功能,您应该可以通过调用 collection.update(MongoDBObject(...), ...) _(附加下划线)来实现
  • 我不明白它是如何在范围内的。我想我需要查看柯里化实现下面的源代码,才能完全理解它确实在范围内。我很难理解什么时候在范围内或不在范围内
  • 我不知道 casbah,所以我可能帮不了你。然而,这与其说是关于柯里化,不如说是关于隐含。看起来在这种情况下,只需要currying来允许添加隐式参数(因为你不能指定例如def f(a: int, implicit b: Int),但由于某种原因只能指定def f(a: Int)(implicit b: Int))也许你可以更新问题以包括所有导入,所以可以能够找出隐含在范围内的位置。
  • 但是在这种情况下,第二个参数列表不是从第一个参数列表中提供的吗?
  • 类型推断将根据第一个参数列表确定泛型类型AB,但除此之外,第一个参数列表不会影响第二个。我的猜测是你导入的东西定义了implicit def f(x: MongoDBObject): DBObject

标签: mongodb scala casbah


【解决方案1】:

Casbah 库订阅了“pimp my library”模式。它扩展了官方的 MongoDB Java 驱动程序并添加了隐式和其他功能,使 Java 驱动程序在 scala 中的使用感觉“原生”。

update 方法如下所示:

  /**
   * Performs an update operation.
   * @param q search query for old object to update
   * @param o object with which to update <tt>q</tt>
   */
  def update[A, B](q: A, o: B, upsert: Boolean = false, multi: Boolean = false,concern: com.mongodb.WriteConcern = this.writeConcern
this.writeConcern)(implicit queryView: A => DBObject,
                            objView: B => DBObject,
                            encoder: DBEncoder = customEncoderFactory.map(_.create).orNull): WriteResult = {
    underlying.update(queryView(q), objView(o), upsert, multi, concern, encoder)
}

Java 驱动程序需要DBObject 进行更新操作,但Casbah 提供了一个Scala 帮助程序来在MongoDBObject 中创建DBObjects。为了提供 Scala 类型和 Java 类型之间的互操作,我们可以使用implicit parameters

由于编译器会在编译时知道A,它可以确定type A =&gt; DBObject 的隐式定义是否在范围内。然后,Casbah 使用该方法 queryView(q)q 转换为 DBObject 并将其传递给底层更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多